Skip to main content
Custom blocks are in private alpha:
  • Do not discuss publicly or share with anyone outside your workspace.
  • Access must be enabled per workspace. Installing the SDK does not grant access.
  • These APIs may experience breaking changes without notice.
A custom block runs in an iframe inside a Notion page. The iframe separates your block from the Notion app. Your block accesses workspace data through Notion’s custom block APIs, with the viewer’s permissions. You control the code and dependencies that run inside your block.

Principles

Custom blocks are designed to be safe for every Notion user. The security model follows three principles:
  • Inherit and respect Notion’s platform security.
  • Prevent a block, including one written by a malicious actor, from reaching sensitive data or executing code in the context of the Notion app.
  • Allow the most expressive use of standard web technologies that those constraints permit.

Isolation from the Notion app

A custom block runs in a sandboxed iframe served from its own dedicated origin, separate from Notion’s. Each block gets its own origin, so two blocks are isolated from each other as well as from the app. Block code has:
  • No access to the Notion app’s DOM or JavaScript context.
  • No access to the Notion app’s cookies, storage, or session.
  • No credentials for Notion APIs or any other service.
  • Restrictions on external requests and resource loads. A workspace owner can allow specific HTTPS origins.
Everything a block knows about Notion, and everything it does to Notion, goes over the host handshake rather than the network.

Browser capabilities and network access

A block can be bound to sensitive data sources. It runs on every page view with the viewer’s permissions. Browser content security policy (CSP) limits external requests and resource loads. Notion-hosted images, audio, and video can load without workspace approval. Google Fonts also works by default. Other external fetch, image, font, stylesheet, audio, video, and iframe destinations require workspace approval. A workspace owner can allow specific HTTPS origins in Settings → Workers → Custom block external network access. The allowlist applies to every custom block in the workspace, so request only origins your block needs. Bundle JavaScript dependencies with your block. Notion-hosted images, audio, and video, plus Google Fonts, work without extra setup. For other external services or resources, ask a workspace owner to add the HTTPS origin, such as https://api.example.com or https://*.example.com, to the allowlist under Settings → Workers → Custom block external network access. An approved external iframe uses its own CSP for requests made inside that page. The block’s network allowlist does not restrict those requests. Approve an iframe origin only if you trust the pages it serves and their dependencies. The block’s sandbox restrictions still apply to nested pages, so forms, popups, and top-level navigation remain blocked. Dependencies that require browser workers or documents loaded through <object> or <embed> do not work in custom blocks. This can affect PDF viewers, editors, and image-processing libraries. The workspace allowlist does not enable these capabilities. Enter only an HTTPS origin, such as https://api.example.com, without a path. You can use a wildcard for subdomains, such as https://*.example.com. The wildcard does not include https://example.com. Add that origin separately if the block needs it. Reload the block after the owner saves the setting. The allowlist changes the block’s content security policy. It does not change the external API’s cross-origin resource sharing (CORS) policy. For fetch or XMLHttpRequest, the API must allow the custom block’s iframe origin in its CORS response.

Permissions

Three related objects govern access to a custom block and the data it can use: the Worker that defines and deploys the block, each instance of the block inserted on a page, and the data sources bound to that instance.
  • Worker: The Worker defines and deploys the custom block capability. Share the Worker with various access levels to make its custom blocks available to workspace members.
    • Can connect: Can find the Worker’s deployed custom blocks, view registered slash commands, and insert instances of the block on any page they can edit.
      Custom block / menu actions are currently only available on desktop and web. Registered commands do not appear in the mobile slash menu.
    • Full access: Can additionally manage, edit, and deploy the Worker.
  • Block instance: A block instance is a custom block inserted into a page, and it inherits the permissions of the page it belongs on.
    • Read-only access: Can view the instance but not edit it.
    • Edit access: Can additionally edit the instance’s data bindings and change which worker block it connects to.
    • Page guests can view custom blocks on shared pages if they can access the containing page and every bound data source.
    • Limitations
      • Custom blocks do not render on pages published with Notion Sites.
  • Bound data sources: A custom block declares a data contract, and each block instance binds its declarations to real Notion data sources. See binding a block to Notion data.
    • Anyone with edit access to the block instance can bind it to a database where they have at least viewer access.
    • The block initializes only if the viewer can access every bound data source. The block UI does not render for viewers without read access. Access to the page containing the block does not by itself grant access to its bound data sources.
    • The block can access only data that the viewer can access. Row-level permissions still apply, so two viewers can see different results from the same block.
    • The block reads and writes with the viewer’s permissions, not the author’s. If the viewer cannot perform a write, the operation returns an access error, even after the block loads. Handle the error in block code. Do not assume that every operation succeeds. See error handling.
Custom blocks run with the viewer’s permissions, meaning it can read private data that its author cannot access directly. A malicious block could copy that data to another page or data source visible to the author.Only use custom blocks from authors you trust. Be careful when binding sensitive data sources to an untrusted block.

Author responsibilities

You are responsible for the secrets and dependencies included in your bundle.

Keep secrets in the worker

Treat all custom block code as public to anyone who can view a page containing the block. Everything you bundle ships to every viewer’s browser. This includes keys, tokens, internal URLs, and unreleased copy. Store them as worker secrets instead, where they stay server-side and never reach the browser.

Vet your dependencies

The network allowlist does not make an untrusted dependency safe. Dependencies can expose workspace or project data in several ways.
  • At runtime, a malicious dependency can send workspace data to an allowed origin. Each allowed origin is available to every custom block in the workspace.
  • Browser restrictions do not reliably block DNS prefetch or WebRTC across browsers.
  • At build time, dependencies run in an isolated build environment with access to your worker project. A malicious dependency can read sensitive project files.
Vet third-party dependencies. Pin them to specific trusted versions, and consider enforcing a minimum release age on your npm dependencies.

Governance

We are working on ways for workspace administrators to have more control over custom blocks. During the private alpha, access is gated by the rollout of the feature itself. Tell us what controls you would like to see.