When to Use
- Single-page application scraping: Fetch the rendered HTML of React or Angular apps where the server returns an empty shell and the content is injected by JavaScript after load.
- Competitor price monitoring: Retrieve a product page after JavaScript renders the dynamic price, then pass the HTML to a parse or transform node to extract the value.
- News and content aggregation: Pull the full article HTML from sites that require JavaScript to reveal paywall-gated or lazy-loaded content sections.
- Automated testing verification: Capture a page's final DOM after a test action and compare key elements against expected values in a subsequent workflow step.
- Data pipeline ingestion: Fetch HTML from a dynamic report portal and feed it to an AI extraction node that parses tables, lists, and structured content.
content vs. scrape: Use
content when you need the full rendered HTML and will parse it downstream. Use
scrape when you already know the CSS selectors for the values you need — scrape returns structured data directly without you having to parse HTML.
Configuration
Connection
| Field | Required | Description |
BaseUrl | Required | Browserless instance URL, e.g. https://chrome.browserless.io or your self-hosted address. |
Token | Optional | API token for cloud Browserless. Omit for self-hosted instances without authentication. |
Operation
| Field | Required | Description |
url | Required | The page URL to navigate to. Supports BizFirst expressions, e.g. {{ $input.productUrl }}. |
gotoOptions | Optional | JSON object controlling navigation. Key fields: waitUntil ("load", "domcontentloaded", "networkidle0", "networkidle2") and timeout in ms. |
waitForSelector | Optional | JSON object with selector (CSS selector string) and optional timeout (ms). Waits for the element to appear in the DOM before returning. |
waitForTimeout | Optional | Fixed wait in milliseconds after the page finishes loading. Use sparingly — prefer waitForSelector or gotoOptions.waitUntil. |
waitForFunction | Optional | JSON object with fn (JS expression to poll) and optional timeout. Waits until the expression returns truthy. |
setJavaScriptEnabled | Optional | Default true. Set to false to disable JavaScript — useful for static sites where JS execution is not needed. |
userAgent | Optional | Override the browser user-agent string. Useful for sites that return different content based on the client. |
viewport | Optional | JSON object with width, height, and optionally deviceScaleFactor. Controls the viewport dimensions used for responsive rendering. |
authenticate | Optional | JSON object with username and password for HTTP Basic or Digest authentication challenges. |
setExtraHTTPHeaders | Optional | JSON object of additional request headers, e.g. {"Authorization": "Bearer token"}. |
cookies | Optional | Array of cookie objects to set before navigation. Each object: name, value, domain. |
rejectResourceTypes | Optional | Array of resource types to block: "image", "media", "font", "stylesheet". Speeds up load time when those resources are not needed. |
blockAds | Optional | Default true. Blocks ad network requests during page load. |
bestAttempt | Optional | Default true. When true, Browserless returns content even if some sub-resources failed to load, rather than erroring. |
useCustomBody | Optional | When true, the raw customBodyJson is sent as the request body, bypassing all field mapping above. |
customBodyJson | Optional | Raw JSON body sent verbatim when useCustomBody is true. |
Sample Configuration
{
"operation": "content",
"baseUrl": "https://chrome.browserless.io",
"token": "{{ $env.BROWSERLESS_TOKEN }}",
"url": "https://shop.example.com/products/{{ $input.productSlug }}",
"gotoOptions": {
"waitUntil": "networkidle2",
"timeout": 20000
},
"waitForSelector": {
"selector": ".product-price",
"timeout": 10000
},
"rejectResourceTypes": ["image", "media", "font"],
"blockAds": true,
"bestAttempt": true
}
Validation Errors
| Error Code | Cause |
VAL_MISSING_URL | url is empty and html is also not provided. |
CFG_INVALID | The node settings could not be resolved — usually indicates a misconfigured operation field. |
BROWSERLESS_BAD_REQUEST | customBodyJson could not be parsed as a valid content request object. |
Output
Success Port
| Field | Type | Description |
status | string | Always "success". |
errorCode | string | Always empty on success. |
operation | string | Always "content". |
url | string | The URL that was fetched. |
html | string | Full rendered HTML of the page after JavaScript execution. |
Error Port
| Field | Type | Description |
status | string | Always "error". |
errorCode | string | Machine-readable error code, e.g. BROWSERLESS_BAD_REQUEST, UNKNOWN_ERROR. |
errorMessage | string | Human-readable description of the failure. |
operation | string | Always "content". |
httpStatusCode | int | HTTP status code from the Browserless API, if available (e.g. 429 for rate limit). |
Sample Output
{
"status": "success",
"errorCode": "",
"operation": "content",
"url": "https://shop.example.com/products/widget-pro",
"html": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><title>Widget Pro — Example Shop</title></head><body><h1 class=\"product-title\">Widget Pro</h1><span class=\"product-price\">$49.99</span><p class=\"stock\">In stock — ships in 2 days</p></body></html>"
}
Expression Reference
| Expression | Value |
{{ $output.BrowserlessNode.html }} | Full rendered HTML string. |
{{ $output.BrowserlessNode.url }} | URL that was fetched. |
{{ $output.BrowserlessNode.status }} | "success" or "error". |
{{ $output.BrowserlessNode.errorCode }} | Error code, empty on success. |
Node Policies & GuardRails
| Policy | Recommendation | Severity |
| External network access | Browserless fetches arbitrary URLs. Validate and allowlist target domains in your workflow logic before passing user-supplied URLs to this node. | High |
| Token storage | Store the Browserless API token in a workflow secret or environment variable — never hardcode it in the node configuration. | Critical |
| Output size | Full-page HTML can exceed several megabytes for complex sites. If downstream nodes have payload limits, extract only the required elements using the scrape operation instead. | Medium |
| Timeout configuration | Always set a gotoOptions.timeout appropriate to the target site. Leaving it at the Browserless default (30 s) for slow sites can block the workflow queue. | Medium |
| Rate limits | Cloud Browserless plans cap concurrent sessions. Use the continueOnError flag and a retry node to handle 429 responses gracefully. | Medium |
Examples
Example 1 — Extract a product price from a React storefront
Fetch the fully rendered page and pass the HTML to a Function node that uses a CSS parser to extract the price.
{
"operation": "content",
"baseUrl": "https://chrome.browserless.io",
"token": "{{ $env.BROWSERLESS_TOKEN }}",
"url": "{{ $input.productUrl }}",
"gotoOptions": { "waitUntil": "networkidle2", "timeout": 15000 },
"waitForSelector": { "selector": "[data-testid='price']", "timeout": 8000 },
"rejectResourceTypes": ["image", "media", "font", "stylesheet"],
"blockAds": true
}
Example 2 — Fetch a behind-login page using cookies
Pass authenticated session cookies so Browserless navigates as a logged-in user.
{
"operation": "content",
"baseUrl": "https://chrome.browserless.io",
"token": "{{ $env.BROWSERLESS_TOKEN }}",
"url": "https://portal.example.com/reports/monthly",
"cookies": [
{ "name": "session_id", "value": "{{ $env.SESSION_COOKIE }}", "domain": "portal.example.com" }
],
"gotoOptions": { "waitUntil": "networkidle0", "timeout": 25000 },
"blockAds": true
}
Example 3 — Disable JavaScript for a static site (faster)
Static HTML sites do not need JavaScript execution. Disabling it cuts response time significantly.
{
"operation": "content",
"baseUrl": "http://browserless.internal:3000",
"url": "https://blog.example.com/archive/{{ $input.slug }}",
"setJavaScriptEnabled": false,
"bestAttempt": true,
"blockAds": true
}