ScreenshotNeo

BlogHow-to

How to Automate Webpage Screenshots from Notion Database Entries with n8n

Build an n8n workflow that reads a URL from a Notion database, captures the page, and routes the image with validation and error handling.

By the ScreenshotNeo team4 October 202612 min read

To automate webpage screenshots from Notion database entries with n8n, store each target page URL in a Notion URL property, trigger an n8n workflow when a page is added or when you explicitly send a webhook, validate the URL, call a screenshot API from an HTTP Request node, then route its binary image output to your chosen storage or notification step.

This guide uses Browserless as the do-it-yourself screenshot API example. The resulting flow is: Notion event → URL validation → screenshot request → image storage or delivery. The example captures a full-page PNG; you can change its scope, format, and viewport for your use case.

1. Prepare the Notion database and choose a trigger

Add a URL property to the database, for example Screenshot URL. Share the database or relevant page with the Notion integration used by n8n. A trigger notification does not by itself guarantee the integration can read every property: access and the database schema still matter.

Choose one trigger based on what should start the capture:

Trigger Use it when Things to check
n8n Notion Trigger You want the workflow to react to the supported page-added-to-database event. Confirm the selected database, credentials, and event behavior in the n8n version and deployment you use.
Notion database automation → Send webhook → n8n Webhook You want a configured Notion automation or button action to call a specific n8n workflow. Notion webhook actions send an HTTP POST and are available on paid plans. The action does not require authentication, so use an unguessable n8n webhook URL and avoid exposing sensitive data in its payload.
Notion connection webhook You need integration-level notifications about changes to shared pages or databases. This is distinct from a database automation action. Select it only if its broader event model fits your workflow.

Notion describes the differences between [connection webhooks and webhook actions](https://www.notion.com/help/create-integrations-with-the-notion-api), and documents [database automation triggers and actions](https://www.notion.com/help/database-automations) and [webhook actions](https://www.notion.com/help/webhook-actions). For a simple “new entry, then capture” workflow, start with the n8n trigger if its supported event matches your need; use a database automation when you specifically want an explicit action, such as a button.

2. Build the n8n workflow

  1. Add the trigger. Create a Notion Trigger for a page added to the target database, or create an n8n Webhook node and paste its production URL into the Notion automation’s Send webhook action. Activate the workflow when using the production webhook URL. Use the test URL only while listening for a test event.
  2. Inspect a real sample event. Add a test database entry and inspect the trigger output. Find the page ID and the URL property value. Notion and n8n payload shapes vary by node and version, so map the actual output instead of assuming a property path.
  3. Validate before capture. Add an IF or Filter node. Continue only if the URL property exists, is non-empty, and is an HTTP or HTTPS URL. If the trigger payload does not include the property value, use a Notion page retrieval step with the page ID, then read the URL from that result.
  4. Call the screenshot API. Add an HTTP Request node. Set method to POST and use the Browserless endpoint and JSON body below. Put the API token in n8n credentials or a secret-backed environment value; do not type it into an exported workflow or a Notion field.
  5. Preserve the image as binary data. Configure the HTTP Request response format as a file/binary response using the current n8n node UI. Set a binary property name, such as data. The precise option label can vary by n8n version. Check the node output for a binary property before connecting storage.
  6. Store or deliver the result. Connect an approved storage, upload, or notification node that accepts the binary property. Choose a filename that includes a sanitized Notion page identifier or date. If you want the file or its link written back to Notion, first choose the storage destination and then configure the appropriate file or URL property behavior; there is no universal destination implied by the screenshot response.
  7. Handle failures and repeat runs. Route missing URLs and HTTP errors to an error branch or log. Decide whether editing an existing Notion entry should create another capture. If captures should be repeatable, define a stable file naming or replacement rule so retries do not create confusing duplicates.

Browserless HTTP Request settings

Browserless documents a POST request to /screenshot, authenticated with a token query parameter. Its documented production example uses the SFO host below. If your account or deployment specifies a different Browserless host, use that host with the same endpoint path.

  • Method: POST
  • URL: https://production-sfo.browserless.io/screenshot?token=YOUR_BROWSERLESS_TOKEN
  • Send body: JSON
  • Response: File/binary; choose a binary property name, for example data
  • Timeout: Set a value that allows the target page to render, within your provider and n8n limits.

Use a credential or secret expression for the token rather than saving its literal value in the URL field. The JSON body for a full-page PNG is:

{
  "url": "https://example.com/",
  "options": {
    "fullPage": true,
    "type": "png"
  }
}

In n8n, map url from the URL property in the trigger or retrieval node using the expression picker. Do not paste a guessed expression from another workflow: property names and output nesting depend on your Notion database and node output.

The [Browserless Screenshot API documentation](https://docs.browserless.io/rest-apis/screenshot-api) describes the endpoint, output formats, full-page option, selector capture, and shared request configuration. Browserless also publishes an [n8n HTTP Request template](https://n8n.io/workflows/) for this type of request; verify its current node fields against your n8n version.

3. Run the API request outside n8n

Use these examples to confirm that the token, endpoint, URL, and response are working before debugging the workflow. Replace the sample target URL as needed. Save the token in an environment variable in your local shell rather than committing it.

cURL

curl -X POST \
  "https://production-sfo.browserless.io/screenshot?token=$BROWSERLESS_TOKEN" \
  -H "Cache-Control: no-cache" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/","options":{"fullPage":true,"type":"png"}}' \
  --output screenshot.png

Python

import os
import requests

endpoint = "https://production-sfo.browserless.io/screenshot"
response = requests.post(
    endpoint,
    params={"token": os.environ["BROWSERLESS_TOKEN"]},
    headers={"Cache-Control": "no-cache"},
    json={
        "url": "https://example.com/",
        "options": {"fullPage": True, "type": "png"},
    },
    timeout=90,
)
response.raise_for_status()
with open("screenshot.png", "wb") as image_file:
    image_file.write(response.content)

Node.js

import { writeFile } from "node:fs/promises";

const endpoint = new URL("https://production-sfo.browserless.io/screenshot");
endpoint.searchParams.set("token", process.env.BROWSERLESS_TOKEN);

const response = await fetch(endpoint, {
  method: "POST",
  headers: {
    "Cache-Control": "no-cache",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://example.com/",
    options: { fullPage: true, type: "png" },
  }),
  signal: AbortSignal.timeout(90_000),
});

if (!response.ok) {
  throw new Error(`Screenshot request failed: ${response.status} ${await response.text()}`);
}
await writeFile("screenshot.png", Buffer.from(await response.arrayBuffer()));

4. Choose capture settings

Need Setting or approach Practical note
Entire long page options.fullPage: true Lazy-loaded images may require scrolling before capture. Browserless documents scrollPage: true for triggering lazy loading; combine it with full-page capture when appropriate.
One section or component Top-level selector, alongside url The API waits for the selected element and captures its bounds. Check that the selector is unique and present on the page.
Fixed viewport region options.clip with x, y, width, and height Use when the required area is known and does not depend on an element’s changing bounds.
Different file type options.type: png, jpeg, or webp Use the matching filename extension and confirm the binary response content type.
Specific resolution Viewport dimensions and device scale factor in screenshot options Choose dimensions for the downstream use. A larger viewport or scale factor usually increases image dimensions and may increase processing and storage needs.
Wait for page state Shared wait configuration, such as waiting for a selector or event Prefer a meaningful page-ready condition over an arbitrary long delay when possible. Set a timeout for pages that never reach the condition.
Reduce unwanted network loads Shared request configuration such as rejecting selected resource types or request patterns Blocking resources can make captures faster, but blocking scripts, stylesheets, or fonts can change the rendered result.
Continue through some wait failures bestAttempt where supported This can permit a capture when an asynchronous wait fails, but it may produce an incomplete page. Inspect output quality rather than treating any image as success.

For high-level captures, use PNG where crisp text or lossless output matters; JPEG or WebP may suit downstream systems that prefer smaller image files. Confirm supported format and option names in the current API documentation before depending on less common options.

5. Validate the URL and prevent unsafe or duplicate captures

  • Reject empty values, whitespace-only values, and values that are not absolute HTTP or HTTPS URLs.
  • Consider an allowlist of domains when database editors are not all trusted. This limits accidental captures of internal or unintended destinations.
  • Do not assume that a syntactically valid URL is reachable, public, or safe for every browser service. Private network URLs and authenticated pages need a deliberate access design.
  • Normalize obvious input issues, such as leading or trailing whitespace, before passing a value to the request.
  • Use a stable identifier, such as the Notion page ID plus a capture version or timestamp, to associate the output with its source record.
  • Before enabling retries, decide whether the storage step overwrites an existing image or creates another file. A retry after a timeout can otherwise leave multiple captures.

6. Troubleshooting

Symptom Likely cause Fix
The workflow does not start The workflow is not active, the wrong webhook URL was configured, or the trigger event does not match what happened. For webhook actions, use the production URL with an active workflow. For a Notion Trigger, confirm the selected database and test the supported event with a new entry.
The URL is missing in the HTTP Request node The trigger output did not include the expected property, the expression points to a guessed path, or the integration lacks access. Inspect the actual trigger data, confirm database sharing, and retrieve the page using its ID if necessary. Remap the URL property from the resulting node output.
HTTP 401 or 403 The API token is missing or invalid, the endpoint host does not match the account, or access to the target page is denied. Check the token credential and account endpoint. Open the target page in an ordinary browser to distinguish provider authentication from target-site access restrictions.
HTTP 400 The request body is invalid JSON, has the wrong shape, or uses an invalid URL or option value. Send a minimal body containing a known-good URL and supported options. Ensure the body is JSON and that selector is at the top level if used.
The response is text or JSON instead of an image The API returned an error response and n8n treated it as a successful file body. Enable error handling or check the HTTP status before storage. Inspect the response body for the actual API error rather than saving it with a PNG extension.
The capture is blank, a CAPTCHA, or an access-denied page The target site may block automated browsers or require access the screenshot service does not have. Verify the page manually and respect the site’s access controls. Do not treat an error or challenge page as the desired screenshot; route it for review or use an authorized access method.
Images or lower sections are absent Lazy loading or client-side rendering had not completed before capture. Use full-page mode with scrolling where supported, wait for a relevant selector or render event, or increase the wait within your timeout budget.
The image is clipped or unexpectedly huge Full-page mode captures the full document, or the viewport, selector, or scale factor differs from the intended output. Use an element selector or fixed clip for a bounded region. Recheck viewport dimensions and device scale factor.
n8n reports no binary property The HTTP Request node response is configured as text/JSON or the binary property name differs from the storage node input. Set the response to file/binary, run the node again, and use the binary property shown in its output when configuring the next node.
Timed-out requests or intermittent failures The target page is slow, a wait condition never occurs, the page is very long, or the service/network is temporarily unavailable. Set a realistic timeout, use a condition tied to the page content, and route failures separately. Retry only transient failures and make the storage step idempotent where possible.
Duplicate images after updates Each page-added or property-edited event creates a new output, or a retry repeats the storage action. Choose whether updates should capture again. Use a predictable replacement key or a versioned filename, and ensure the workflow handles repeat events intentionally.

7. Performance, reliability, and cost

Capture time depends on the target page, its assets, wait conditions, capture dimensions, and the screenshot service. The research sources do not establish a universal end-to-end latency promise, so avoid designing around a fixed delivery time. Measure your own representative pages and set n8n timeouts to cover normal page rendering while still allowing failures to surface.

Full-page captures and high-resolution output can produce larger files and use more browser and storage resources than a viewport or selector capture. If the workflow processes many database entries, control concurrency and avoid launching unnecessary duplicate captures. Store enough metadata to trace each image to the source page, and retain the API response status or error in the workflow run so failures are diagnosable.

n8n offers Cloud and self-hosted deployment choices. With Cloud, the service operates the n8n environment; self-hosting makes the operator responsible for its runtime and network configuration. Select based on your operations, data handling, and maintenance needs. No price comparison or delivery guarantee is assumed here.

Browserless request costs and limits depend on its current account terms; check those before processing at scale. This guide does not assume a specific Browserless plan, quota, or per-capture price. Also account for downstream storage and n8n execution limits in your own setup.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. A single GET request can return a PNG, JPEG, WebP, or PDF. It removes cookie banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed; and an MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000 shots. See the ScreenshotNeo API documentation.

In the n8n HTTP Request node, use GET, map the Notion URL property to url, and send your ScreenshotNeo access key as a credential-backed query parameter:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.com/ \
  -o shot.webp

Set the HTTP Request node response to file/binary and pass that binary property to the same storage or delivery step in your workflow. ScreenshotNeo also supports full-page capture, CSS selector capture, device and viewport settings, custom CSS and JavaScript, wait conditions, caching, async jobs, and bulk capture; see the docs for parameter names and available options.

Sign up free for 1,000 screenshots a month with no card.

FAQ

Can I capture a screenshot when an existing Notion URL changes?

Yes, if your selected trigger or Notion automation reacts to that property edit. Configure the event deliberately and decide whether an edit should replace the prior image or create a new version.

Can the image be added back to the same Notion entry?

Yes, but the storage destination and Notion property type determine the steps. First upload or store the binary image somewhere your workflow can access, then write the resulting file or link using the appropriate Notion behavior for your setup.

Does a webhook event guarantee the screenshot is ready immediately?

No fixed end-to-end timing is established here. The workflow must wait for the screenshot request and any downstream storage action to finish, and each may fail independently.

Should I use a Notion trigger or a webhook action?

Use the trigger whose event scope matches your workflow. The n8n trigger is a direct event-based option; a Notion webhook action is useful when a database automation or button should explicitly call the workflow.