n8n+DiffHook

n8n + Playwright — JS-rendered scraping without the browser fleet

DiffHook runs Playwright for you on every check, waits for the page to finish rendering, diffs the result, and POSTs changes to n8n over a signed webhook. No headless Chromium to install, no stealth plugins to patch.

Scraping a React or Vue SPA from n8n usually means stitching together the Browserless node, a custom Docker image with Playwright installed, or a third-party scraping API with its own auth and rate-limit dance. All of them put a browser inside your n8n deployment. DiffHook flips the model: the browser runs on our side, fully managed, and only the diff crosses the wire — everything else stays the same simple n8n webhook pattern.

n8n

The complete n8n + DiffHook hub

See every n8n recipe, template, and pricing tier in one place.

Workflow

Wire Playwright-rendered diffs into n8n in 5 steps

No Docker image, no Browserless credit, no Playwright install. The browser runs inside DiffHook.

01

Expose an n8n webhook

Create or reuse an n8n workflow with a Webhook trigger node. Copy the production URL — DiffHook will deliver to it whenever the rendered DOM changes.

02

Pick html_rendered and the Playwright engine

Set type to html_rendered and render.engine to playwright. Add wait_for_selector or wait_until: networkidle so DiffHook snapshots only once the client-side app has settled.

03

Isolate the target with a CSS selector

After Playwright finishes rendering, DiffHook runs the selector against the resolved DOM. A tight selector keeps the diff focused and avoids n8n workflows firing on unrelated UI changes.

04

Register the monitor

POST once to /v1/monitors with the URL, render config, selector, interval, and the n8n webhook as a delivery. DiffHook schedules the browser runs and caches the last-good DOM.

05

Receive the post-render diff in n8n

On every change, n8n's Webhook trigger fires with previous_value, current_value, and render metadata. Verify HMAC, then route the diff to downstream nodes exactly as you would for a static page.

API example

Playwright-rendered monitor, one POST

render.engine picks the browser — swap to puppeteer any time. wait_for_selector keeps the snapshot stable on JS-heavy pages.

POST /v1/monitors
POST https://api.diffhook.com/v1/monitors
Authorization: Bearer $DIFFHOOK_API_KEY
Content-Type: application/json

{
  "type": "html_rendered",
  "url": "https://spa.example.com/dashboard",
  "render": { "engine": "playwright", "wait_for_selector": ".data-loaded" },
  "css_selector": "#metric-value",
  "interval_seconds": 600,
  "deliveries": [
    {
      "type": "webhook",
      "url": "https://n8n.yourdomain.com/webhook/rendered-change"
    }
  ]
}

Importable workflow

Start from a ready-made n8n workflow

The template verifies the HMAC, pulls the extracted text out of the rendered DOM, and posts a neat summary to Slack. Import, paste your key, done.

FAQ

n8n Playwright — common questions

When should I choose Playwright over the plain HTML engine?
Any time the content you care about is rendered client-side — React, Vue, Svelte, or anything that fetches data after document load. If curl against the URL returns an empty shell or a "loading" placeholder, you need html_rendered. If the data is in the raw HTML DiffHook downloads with a fetch, stick with html_css — it's much faster and cheaper.
How does DiffHook decide the page has finished rendering?
Two mechanisms. Either wait_for_selector (DiffHook waits up to 30 seconds for the selector to appear in the DOM) or wait_until: networkidle (the page is considered ready once there are no network requests for 500ms). Both are configurable per monitor so you can tune for flaky sites.
Can I pass custom headers or cookies to Playwright?
Yes. Each monitor accepts a request_headers map and a cookies array. Auth tokens, regional preference cookies, A/B test pins — all can be scoped to the monitor and stored encrypted. Useful when the rendered view changes by user segment and you want to watch a specific one.
Is Playwright heavier on my plan limits?
Rendered checks count for more than plain HTML checks (they use a real browser), but the ratio is bounded. The free tier allows a small number of rendered checks per day; paid plans scale linearly. The dashboard shows the effective cost of each monitor so there are no surprises.
What about CAPTCHAs and bot protection?
DiffHook's Playwright fleet runs with realistic user agents, TLS fingerprints, and stealth patches, which handles most generic WAF rules. For sites behind Cloudflare Turnstile or hCaptcha, you can pass a solved token via request_headers or switch to the Puppeteer engine which has different browser profiles — sometimes one gets through where the other doesn't.

Related workflows

Also great with DiffHook

Stop hosting a browser just to diff a page

Rendered scraping, Playwright and Puppeteer engines, HMAC-signed webhooks, free tier. Start in under a minute.