Skip to Content

scrape (sync)

POST /api/scrape

scrape a single url and get the full result in the response. requires a bearer token — see authentication.

request

curl -X POST https://api.crawlbrulee.com/api/scrape \ -H "Authorization: Bearer $CRAWLBRULEE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com", "extract": { "markdown": true, "links": true, "images": true } }'

response

a 200 response includes the fields you requested via the extract object. fields you didn’t request are omitted from the response.

a 200 means we got a page from the site — not that the site answered 200. a 404 or 503 page comes back as a 200 from us, with its content and the site’s status in page_status_code. check that field before you use the content. see our status vs. the page’s status.

fieldtypedescription
urlstringthe url actually scraped — after any redirects, in normalized form. /api/map writes its links the same way, so the two agree on the same page. links, images, and internal labels are computed against it
requested_urlstringthe url you requested, echoed verbatim — before any redirects
page_status_codeintegerthe http status the site answered with for the final page, after redirects (in the browser: the main document, not images or scripts). always present. a 404 page is data, not an error; the status also decides whether the page is billed
content_typestringmime type of the page (e.g., text/html)
unsupported_fieldsstring[]fields requested but not supported for this content type (e.g. elements or metadata of a json page)
markdownstringcleaned markdown (when extract.markdown: true)
cleaned_htmlstringcleaned html — returned by default (unless extract.cleaned_html: false)
raw_htmlstringraw source html (when extract.raw_html: true)
linksarraypage links (when extract.links: true) — each: { text, href, internal }
imagesarraypage images (when extract.images: true) — each: { url, alt }
screenshotobjectscreenshot data (when extract.screenshot is set) — see screenshots
elementsobjectthe values asked for in extract.elements, under the same names: a string, an object, a list, or null — see elements
metadataobjectpage metadata — returned by default (unless extract.metadata: false)
response_metaobjectoperation metadata for this response (usage/billing) — see core concepts
response_meta.usage.total_credit_costintegercredits charged for this request: engine_credit_cost × proxy_multiplier + screenshot_slicing_credit_cost + zero_data_retention_credit_cost. 0 on a fully cached result or a page we don’t bill
response_meta.usage.engine_credit_costintegerthe engine base charged: 1 http, 3 browser, 5 screenshot, 0 cache — and 0 when the page isn’t billed
response_meta.usage.proxy_multiplierinteger1 for basic, 5 for advanced
response_meta.usage.screenshot_slicing_credit_costinteger1 when screenshot slices were made on this request, otherwise 0. 0 when the page isn’t billed
response_meta.usage.zero_data_retention_credit_costinteger1 when the request used zero data retention and the result was billed and fresh, otherwise 0
response_meta.usage.enginestringdelivered billing engine: "http", "browser", "screenshot", or "cache"
response_meta.usage.proxystringthe proxy tier that actually resolved the request — the resolved tier, never "auto"
warningsstring[]non-error notices — an output was capped rather than delivered whole (e.g. screenshot_truncated, links_truncated, elements_truncated) or couldn’t be extracted (e.g. links_unavailable). screenshot_unavailable means the page came back through the http engine without the screenshot you asked for. filtered to the outputs you requested. see limits and truncation

response example

{ "url": "https://example.com", "requested_url": "https://example.com", "page_status_code": 200, "content_type": "text/html", "markdown": "# Example Domain\n\nThis domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.\n\n[More information...](https://www.iana.org/domains/example)", "cleaned_html": "<h1>Example Domain</h1><p>This domain is for use in illustrative examples...</p>", "links": [ { "text": "More information...", "href": "https://www.iana.org/domains/example", "internal": false } ], "metadata": { "title": "Example Domain", "og_title": "Example Domain", "favicon_url": "https://example.com/favicon.ico" }, "response_meta": { "usage": { "total_credit_cost": 1, "engine_credit_cost": 1, "proxy_multiplier": 1, "screenshot_slicing_credit_cost": 0, "zero_data_retention_credit_cost": 0, "engine": "http", "proxy": "basic" } } }

metadata fields

the metadata object is included by default. set extract.metadata: false to skip it. every field is optional — only fields present on the page appear in the response; absent fields are omitted entirely (never null), with one exception: metadata.favicon_url may be null when no favicon could be resolved.

fieldtypedescription
titlestringpage <title>
descriptionstringmeta description
keywordsstring[]meta keywords
canonicalstringcanonical url from <link rel="canonical">
og_urlstringOpen Graph url
og_titlestringOpen Graph title
og_descriptionstringOpen Graph description
og_typestringOpen Graph type (e.g., website, article)
og_site_namestringOpen Graph site name
og_localestringOpen Graph locale (e.g., en_US)
og_locale_alternatestring[]alternate Open Graph locales
og_imagestringOpen Graph image url
authorstringpage author
date_modifiedstringlast modified date
date_publishedstringpublished date
twitter_sitestringTwitter site handle
twitter_cardstringTwitter card type
twitter_descriptionstringTwitter card description
twitter_titlestringTwitter card title
twitter_imagestringTwitter card image url
robotsstringrobots meta directive
favicon_urlstringbest-effort favicon url for the page

error responses

statusnamewhen
400invalid_url, url_too_long, scrape_errorbad url, url exceeds 8,192 bytes, or a request we could not process as sent
400unsupported_url_schemaonly http and https are supported
400url_credentials_not_supportedurls with embedded credentials are rejected
400blocked_urlurl is not allowed to be scraped
400validation_errorrequest body failed validation — for example an invalid css selector in extract.elements
401invalid_credentialsinvalid or missing api token
403antibot_blockedthe target site’s anti-bot protection blocked the scrape
403zero_data_retention_not_enabledyou sent zero_data_retention: true, but it is not enabled for your organization — not billed. see zero data retention
408request_timeoutscrape took too long
415unsupported_contenttarget content type not supported for extraction
422unsupported_screenshot_outputthe request asked only for a screenshot and the content type can’t be screenshotted (json, plain text, markdown, xml) — not billed
422too_many_redirectsthe target site redirected the request in a loop, or through more hops than we follow. not a bad request; retrying rarely helps
422page_too_largethe page’s html was too large or too complex to convert. terminal — the same url fails the same way, so don’t retry it
429too_many_requests, usage_allocation_errorrate limit or credit/concurrency limit hit
499client_closed_requestclient disconnected before completion
500internal_server_errorserver-side failure — including a screenshot-only request whose capture failed (not billed)
502target_unreachablewe could not reach the site at all — for example, it did not answer in time or its tls certificate is invalid. not billed; a later retry can help
503service_unavailabletransient failure on our end — retry the same request; not an auth problem

a page the site served with an error status (404, 500…) is not in this table: it comes back as a 200 with page_status_code.

all errors follow the standard { name, message, details? } format. see errors for the full reference, and when no screenshot can be delivered for the screenshot-only failure semantics.

combining extraction options

you can request multiple extraction types in a single call — see extraction options for the full field reference. pass everything you need in the extract object, including a screenshot:

{ "url": "https://news.ycombinator.com", "extract": { "markdown": true, "cleaned_html": true, "links": true, "images": true, "screenshot": { "type": "full_page" } } }

request only what you need. each field you skip means less processing and a faster response.

if you don’t pass an extract object, you’ll get metadata + cleaned_html back. add markdown, raw_html, links, images, or screenshot to request more.