Cloud Data API
One-shot screenshots, page content, and structured scraping over HTTPS. No client library required.
What it is
Three HTTPS endpoints on cdp.browsergateway.io that return page data directly, without a Puppeteer or Playwright client. Point curl at them and you get back an image, a markdown document, or a JSON object of selector matches.
| Endpoint | Returns | Body cap |
|---|---|---|
POST /v1/screenshot | Raw image bytes (PNG or JPEG) | 25 MB |
POST /v1/content | JSON with page content in one or more formats | 10 MB |
POST /v1/scrape | JSON with CSS-selector matches, optional formats and screenshot | 5 MB |
Every successful call counts as one BYOK session against your monthly ceiling (10,000 sessions per month, free). Errors (4xx and 5xx responses) never count. Above the ceiling each call costs $0.0005 from the wallet.
This is a distinct surface from two others on the platform:
| Surface | Base URL | Auth | Purpose |
|---|---|---|---|
| Cloud Data API (this page) | https://cdp.browsergateway.io/v1 | Router key Bearer bg_... | One-shot browser actions |
| Cloud CDP endpoint | wss://cdp.browsergateway.io/v1/connect?token=bg_... | Router key in query string | Full CDP session for Puppeteer / Playwright |
| Cloud REST API | https://app-api.browsergateway.com/v1 | Account token Bearer bga_... | Manage workspaces, providers, billing |
The router key and the account token are separate systems. The router key powers CDP + Data API; the account token powers the control-plane API.
Auth
Every request carries the router key in the Authorization header:
curl -X POST "https://cdp.browsergateway.io/v1/screenshot" \
-H "Authorization: Bearer bg_YOUR_ROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'Alternatively, pass the key as ?token=:
curl -X POST "https://cdp.browsergateway.io/v1/screenshot?token=bg_YOUR_ROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'The router key is the same one you paste into Puppeteer or Playwright for CDP connections. Find it on the Keys & access page in the dashboard. The key decides which router, and so which providers, serve the call.
Billing
Every successful call = one BYOK session. First 10,000 sessions per month are free across your workspace (CDP + Data API combined). Above that, each call draws $0.0005 from the wallet.
Data API calls are not refused when the workspace is over the ceiling with an empty wallet. The charge is still recorded, the balance goes below zero, and the next top-up settles it. See Billing.
Data API calls share the same monthly ceiling as CDP sessions. Pick whichever interface fits your code; both count the same way toward the ceiling.
Responses and errors
| Response | Meaning | Counts as session? |
|---|---|---|
| 200 | Success | Yes |
| 400 | Validation error, no providers on the router, or provider is not on this router | No |
| 401 | Missing or wrong router key | No |
| 408 | The page or the provider connection timed out | No |
| 413 | Response body exceeded the endpoint cap | No |
| 429 | The router queue timed out waiting for a free provider (honour Retry-After), or too many failed auth attempts came from your IP | No |
| 500 | The browser action failed | No |
| 503 | No provider available (all switched off, cooling down or at capacity), every provider failed to connect, or the router queue is full | No |
Error bodies are JSON:
{ "success": false, "error": "Provider 'browserserve-eu' unavailable (in cooldown or at capacity)" }Validation errors add a details array. The two auth errors (401 and the 429 for failed attempts) are plain text.
Every successful response names the provider that served it in the X-Provider-Slug header. /v1/content and /v1/scrape also return it as provider in the JSON body.
Timeouts
timeout is the navigation timeout in milliseconds: default 30000, from 1000 to 120000. The whole request is allowed timeout plus 20 seconds, to cover connecting to the provider and sending the response. Raise timeout for slow pages or slow providers if you see 408 responses.
/v1/screenshot
Capture a screenshot of any URL as PNG or JPEG. Response body is raw image bytes.
curl -X POST "https://cdp.browsergateway.io/v1/screenshot" \
-H "Authorization: Bearer bg_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "png",
"fullPage": true,
"viewport": { "width": 1440, "height": 900 }
}' \
--output screenshot.pngRequest body:
| Field | Type | Default | Notes |
|---|---|---|---|
url | string | required | Fully qualified URL to load |
format | "png" | "jpeg" | "png" | Image format |
fullPage | boolean | false | Scroll and capture the entire scrollable area |
viewport | {width, height} | {1280, 720} | Browser viewport |
quality | number 0-100 | JPEG only | |
selector | string | Capture the first element matching this CSS selector | |
clip | {x, y, width, height} | Capture only a region | |
omitBackground | boolean | false | Transparent background (PNG only) |
scrollPage | boolean | false | Scroll through before capture to trigger lazy loading |
waitUntil | string | "domcontentloaded" | load, domcontentloaded, networkidle, commit |
waitForSelector | string | Wait for this selector after navigation (10 s cap) | |
waitForTimeout | number | Extra ms to wait after load (0 to 30000) | |
timeout | number | 30000 | Navigation timeout in ms (1000 to 120000). See Timeouts. |
headers | object | Extra HTTP request headers | |
userAgent | string | Override the browser's user agent |
Response headers:
Content-Type:image/pngorimage/jpegX-Response-Code: upstream HTTP status of the navigated pageX-Response-URL: final URL after any redirectsX-Timing-Total-Ms: end-to-end wall clockX-Timing-Navigation-Ms: time spent on navigationX-Provider-Slug: the provider that served the call
/v1/content
Fetch a page and return its content in one or more formats. Useful for AI agents that want clean text or markdown.
curl -X POST "https://cdp.browsergateway.io/v1/content" \
-H "Authorization: Bearer bg_..." \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com", "formats": ["markdown", "text"] }'Request-body fields extend the screenshot base with:
| Field | Type | Default | Notes |
|---|---|---|---|
formats | string[] | ["markdown"] | Any combination of html, markdown, text, readability |
Response shape:
{
"success": true,
"provider": "browserless-eu",
"data": {
"url": "https://example.com/",
"statusCode": 200,
"content": {
"markdown": "# Example Domain\n\nThis domain is for use...",
"text": "Example Domain\n\nThis domain is for use..."
},
"metadata": {
"title": "Example Domain",
"description": "..."
},
"links": [
{ "url": "https://www.iana.org/domains/example", "text": "More information..." }
]
},
"timings": { "total": 432, "navigation": 380, "action": 52 }
}readability runs the page through a Readability-style extractor (removes chrome, isolates the main article). markdown runs the extractor with markdown output. html returns raw serialized HTML. text returns document.body.innerText.
/v1/scrape
Extract structured data using CSS selectors. Optionally combines selector results with page content and a screenshot in one round-trip.
curl -X POST "https://cdp.browsergateway.io/v1/scrape" \
-H "Authorization: Bearer bg_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"selectors": [
{ "name": "title", "selector": "h1" },
{ "name": "links", "selector": "a", "attribute": "href" }
],
"formats": ["markdown"]
}'Additional request-body fields:
| Field | Type | Notes |
|---|---|---|
selectors | array<{name, selector, attribute?}> | Named CSS queries. Each returns matches with text + outer HTML, optionally an attribute value |
formats | string[] | Also return page content in the requested formats |
screenshot | boolean | Also return a base64-encoded JPEG screenshot |
Either selectors or formats (or both) must be provided.
Response shape:
{
"success": true,
"provider": "browserless-eu",
"data": {
"url": "https://example.com/",
"statusCode": 200,
"selectors": [
{
"name": "title",
"selector": "h1",
"results": [{ "text": "Example Domain", "html": "<h1>Example Domain</h1>" }]
}
],
"content": { "markdown": "# Example Domain..." }
},
"timings": { "total": 380, "navigation": 350, "action": 30 }
}Profiles are not supported
The request schema accepts a profile field, but the cloud Data API ignores it: calls always run in a fresh browser without saved cookies or storage. To run with a saved profile, connect through the Cloud CDP endpoint with ?profile=<slug>.
Provider pinning
Pass provider to route the request to one specific backend (no failover):
{
"url": "https://example.com",
"provider": "browserserve-eu"
}If the pinned provider is not on the router, the response is HTTP 400. If it is cooling down or at capacity, the response is HTTP 503 with no failover attempted.
Try it from the dashboard
The REST API page in the dashboard has an interactive form for each of the three endpoints, autofilled with your active router key.