Skip to main content
Glama

Scrape a URL

scrape

Fetch a single URL and return selected page content—markdown, HTML, links, images, screenshots, or metadata—for one-shot extraction; use CSS selectors to pull named values like prices and titles.

Instructions

Fetch a single URL via the crawlbrulee scraping API and return the requested content (markdown, cleaned HTML, raw HTML, links, images, screenshot, page metadata in metadata). Use this for one-shot page extraction. For full-site discovery use the map tool first. To pull named values such as prices, titles or links, set extract.elements (name → CSS selector) instead of reading the whole markdown: they come back in elements, for no extra credits. Rules: https://crawlbrulee.com/docs/scrape/elements. Check page_status_code before you trust the content: it is the HTTP status the site answered with for the final page. A page the site served is a successful result whatever its status, so a 404 or 503 page comes back with its content, not as an error. A 404 means the markdown is the site's "not found" page, not the page you asked for. 2xx and 4xx pages are billed, except 403, 407, 408, 429 and 451; 5xx pages are never billed. If the site cannot be reached at all the tool returns a target_unreachable error (HTTP 502, not billed): retry later or check the URL. Screenshot URLs in the response are signed download links that expire 24 hours after the scrape: download the image if you need it later; do not keep the link. The response also carries response_meta.usage: total_credit_cost = engine_credit_cost × proxy_multiplier + screenshot_slicing_credit_cost + zero_data_retention_credit_cost, plus engine and proxy (the resolved tier — never auto). engine is the billed engine (http, browser, screenshot, cache); a cache hit is represented by engine: "cache". Set zero_data_retention: true to keep the result out of the shared cache; anything stored to deliver it is kept for 24 hours, then deleted. It adds 1 credit and must be enabled for the organization (else a zero_data_retention_not_enabled error, not billed). See https://crawlbrulee.com/docs/zero-data-retention. Extraction is capped per page: 30,000 links, 10,000 inline images and 10,000,000 characters of HTML. A page past a cap is truncated rather than refused, and the response warnings array names which one (links_truncated, inline_images_truncated, raw_html_truncated) — so treat that output as incomplete. elements_truncated means an elements value hit a limit. Use cleanup to control what is removed before any output is built: ads_and_popups (on by default) drops ads, cookie banners and chat widgets, and exclude_selectors removes anything else. It shapes markdown, cleaned_html, links, images and the screenshot, and NEVER raw_html — so request raw_html when you need the page exactly as it arrived. warnings also reports a section whose extraction failed outright (links_unavailable, inline_images_unavailable, metadata_unavailable): that field comes back omitted or empty while the rest of the scrape succeeded, so do NOT conclude the page had no links/images/metadata — re-run the scrape instead. An empty field with no such warning does mean the page had none. screenshot_unavailable means a screenshot was asked for, but the page came back from the http engine without one.

Input Schema

NameRequiredDescriptionDefault
urlYesThe URL to scrape. Known tracking parameters are removed before the page is fetched, so they are neither sent to the target site nor part of the cache key. Every other query parameter is kept verbatim and is part of the cache key.
cacheNoCache settings for this request
proxyNoProxy tier to use for fetchingauto
cleanupNoWhat is removed from the page before any output is built. Applies to markdown, cleaned_html, links and images on every engine, and to the screenshot. Never applies to raw_html, which is always the page before we removed anything.
extractNoWhich content formats to extract. Defaults to metadata + cleaned_html.
locationNoOptional locale + country emulation for the scrape
require_jsNoUse a headless browser to render JavaScript before scraping
zero_data_retentionNoKeeps the result out of the shared cache; anything stored to deliver it is kept for 24 hours, then deleted. Adds 1 credit. Must be enabled for your organization. See https://crawlbrulee.com/docs/zero-data-retention.

Output Schema

NameRequiredDescriptionDefault
urlYesThe URL that was actually scraped, after any redirects, in normalized form — the base that links, images, and internal labels are computed against
linksNoLinks found on the page
imagesNoInline images found on the page
elementsNoThe values asked for in `extract.elements`, under the same names. Each name is a string, an object (a spec with `fields`), a list of either (`all: true`), or null when nothing matched (`[]` with `all: true`). An object holds its field names with the same kinds of values, nested up to 3 levels. Every requested name is always present, at every level of `fields`.
markdownNoPage content converted to clean Markdown
metadataNoExtracted page metadata (title, OG tags, etc.)
raw_htmlNoRaw, unprocessed HTML of the page
warningsNoNon-error notices about the scrape. Truncation codes — `screenshot_truncated` (long page exceeded the scrolling-screenshot height cap), `links_truncated` / `inline_images_truncated` (page had more links/images than the per-page extraction caps), `raw_html_truncated` (rendered HTML exceeded the per-page size budget) — mean the field is present but capped. `elements_truncated` means at least one `elements` value hit a limit: a list was cut at 1,000 matches, the request reached 10,000 matches in total, or a value did not fit the ~1 MB of values allowed per request (that value is then null, never cut short). Unavailability codes — `links_unavailable` / `inline_images_unavailable` / `metadata_unavailable` — mean that optional field could not be extracted and was omitted (null/empty) while the rest of the scrape succeeded, so an empty field carrying one of these does NOT mean the page had none. `screenshot_unavailable` means a screenshot was asked for, but the page came back from the http engine without one. Stable string codes — clients can switch on them. Warnings are stored with the result: async result fetches and cache hits carry them too, filtered to the fields the request asked for. `metadata_truncated` is retired and no longer sent: metadata has no size limit of its own now, though the code can still appear on results stored before that change.
screenshotNoScreenshot of the page, if requested
cleaned_htmlNoCleaned HTML of the main page content
content_typeNoContent-Type header returned by the server
requested_urlYesThe URL you requested, echoed verbatim — before any redirects
response_metaYesRequest-level metadata. `response_meta.usage` reports what the request cost (total_credit_cost and its parts), the billed engine and the resolved proxy tier.
page_status_codeNoThe HTTP status the site answered with for the final page, after redirects. Check it before you trust the content. A page the site served is a successful result whatever its status: a 404 or 503 page comes back with its content here, not as an error, so a 404 means the markdown is the site's "not found" page, not the page you asked for. Billing follows this status: 2xx and 4xx pages are billed, except 403, 407, 408, 429 and 451; 5xx pages are never billed. Older api versions do not send it; they only returned pages that loaded normally.
unsupported_fieldsNoExtract fields that were requested but are not supported for this content type

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed5 schema fields changedv1.3.3
    • changedInput schema / properties / cache / properties / max_age / anyOf
      Previous value: -[
      -  {
      -    "maximum": 9007199254740991,
      -    "minimum": 0,
      -    "type": "integer"
      -  },
      -  {
      -    "format": "date-time",
      -    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "maximum": 9007199254740991,
      +    "minimum": 0,
      +    "type": "integer"
      +  },
      +  {
      +    "format": "date-time",
      +    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
      +    "type": "string"
      +  }
      +]
    • removedOutput schema / properties / images / items / properties / alt / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / images / items / properties / alt / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / metadata / properties / favicon_url / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / metadata / properties / favicon_url / type
      Added value: +[
      +  "string",
      +  "null"
      +]
  2. Changed14 schema fields changedv1.1.1
    • changedInput schema / properties / extract / properties / cleaned_html / description
      Previous value: -"Extract cleaned HTML (main content only)"New value: +"Extract cleaned HTML: the page body with scripts, styles, ads and cookie banners removed"
    • addedInput schema / properties / extract / properties / elements
      Added value: +{
      +  "additionalProperties": {
      +    "anyOf": [
      +      {
      +        "maxLength": 500,
      +        "type": "string"
      +      },
      +      {
      +        "additionalProperties": false,
      +        "properties": {
      +          "all": {
      +            "default": false,
      +            "description": "Return every match as a list instead of the first. Defaults to false",
      +            "type": "boolean"
      +          },
      +          "attribute": {
      +            "description": "The attribute to read when `output` is `attribute`. `href` and `src` come back as full urls",
      +            "maxLength": 100,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "fields": {
      +            "additionalProperties": {
      +              "anyOf": [
      +                {
      +                  "maxLength": 500,
      +                  "type": "string"
      +                },
      +                {
      +                  "additionalProperties": false,
      +                  "properties": {
      +                    "all": {
      +                      "default": false,
      +                      "type": "boolean"
      +                    },
      +                    "attribute": {
      +                      "maxLength": 100,
      +                      "minLength": 1,
      +                      "type": "string"
      +                    },
      +                    "fields": {
      +                      "additionalProperties": {
      +                        "anyOf": [
      +                          {
      +                            "maxLength": 500,
      +                            "type": "string"
      +                          },
      +                          {
      +                            "additionalProperties": false,
      +                            "properties": {
      +                              "all": {
      +                                "default": false,
      +                                "type": "boolean"
      +                              },
      +                              "attribute": {
      +                                "maxLength": 100,
      +                                "minLength": 1,
      +                                "type": "string"
      +                              },
      +                              "fields": {
      +                                "additionalProperties": {
      +                                  "anyOf": [
      +                                    {
      +                                      "maxLength": 500,
      +                                      "type": "string"
      +                                    },
      +                                    {
      +                                      "additionalProperties": false,
      +                                      "properties": {
      +                                        "all": {
      +                                          "default": false,
      +                                          "type": "boolean"
      +                                        },
      +                                        "attribute": {
      +                                          "maxLength": 100,
      +                                          "minLength": 1,
      +                                          "type": "string"
      +                                        },
      +                                        "output": {
      +                                          "enum": [
      +                                            "text",
      +                                            "html",
      +                                            "attribute"
      +                                          ],
      +                                          "type": "string"
      +                                        },
      +                                        "selector": {
      +                                          "maxLength": 500,
      +                                          "type": "string"
      +                                        }
      +                                      },
      +                                      "required": [
      +                                        "selector"
      +                                      ],
      +                                      "type": "object"
      +                                    }
      +                                  ]
      +                                },
      +                                "propertyNames": {
      +                                  "type": "string"
      +                                },
      +                                "type": "object"
      +                              },
      +                              "output": {
      +                                "enum": [
      +                                  "text",
      +                                  "html",
      +                                  "attribute"
      +                                ],
      +                                "type": "string"
      +                              },
      +                              "selector": {
      +                                "maxLength": 500,
      +                                "type": "string"
      +                              }
      +                            },
      +                            "required": [
      +                              "selector"
      +                            ],
      +                            "type": "object"
      +                          }
      +                        ]
      +                      },
      +                      "propertyNames": {
      +                        "type": "string"
      +                      },
      +                      "type": "object"
      +                    },
      +                    "output": {
      +                      "enum": [
      +                        "text",
      +                        "html",
      +                        "attribute"
      +                      ],
      +                      "type": "string"
      +                    },
      +                    "selector": {
      +                      "maxLength": 500,
      +                      "type": "string"
      +                    }
      +                  },
      +                  "required": [
      +                    "selector"
      +                  ],
      +                  "type": "object"
      +                }
      +              ]
      +            },
      +            "description": "Used instead of `output`: turns each match into an object of named values, each read inside that match only. Same shape as `elements`; nests up to 3 levels",
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "output": {
      +            "description": "What to return for a match: `text` (default), `html` (the outer HTML) or `attribute`",
      +            "enum": [
      +              "text",
      +              "html",
      +              "attribute"
      +            ],
      +            "type": "string"
      +          },
      +          "selector": {
      +            "description": "CSS selector, up to 500 characters",
      +            "maxLength": 500,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "selector"
      +        ],
      +        "type": "object"
      +      }
      +    ]
      +  },
      +  "description": "Named values to read from the page by CSS selector, returned in the top-level `elements` field under the same names. Each value is either a selector string (the text of the first match) or an object with `selector`, `output`, `attribute` and `all`. `fields` (instead of `output`) turns each match into an object of named values read inside that match only, so a list of product cards can return a title, price and url per card. A name with no match is null, or [] with `all: true`. Read after cleanup; `<script>` and `<style>` tags are not part of it. An invalid selector is a 400. No extra credits, also when the page comes from cache. Limits and selector rules: https://crawlbrulee.com/docs/scrape/elements.",
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • changedInput schema / properties / extract / properties / metadata / description
      Previous value: -"Extract page metadata (title, description, OG tags, etc.). Read from the page head, which is capped at 2,000,000 characters — a larger head is truncated and the response carries a `metadata_truncated` warning."New value: +"Extract page metadata (title, description, OG tags, etc.) from the page head"
    • addedInput schema / properties / zero_data_retention
      Added value: +{
      +  "description": "Keeps the result out of the shared cache; anything stored to deliver it is kept for 24 hours, then deleted. Adds 1 credit. Must be enabled for your organization. See https://crawlbrulee.com/docs/zero-data-retention.",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / elements
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "The values asked for in `extract.elements`, under the same names. Each name is a string, an object (a spec with `fields`), a list of either (`all: true`), or null when nothing matched (`[]` with `all: true`). An object holds its field names with the same kinds of values, nested up to 3 levels. Every requested name is always present, at every level of `fields`.",
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • changedOutput schema / properties / response_meta / properties / usage / description
      Previous value: -"What this request cost and why: total_credit_cost = engine_credit_cost × proxy_multiplier + screenshot_slicing_credit_cost, plus the billed engine and the resolved proxy tier."New value: +"What this request cost and why: total_credit_cost = engine_credit_cost × proxy_multiplier + screenshot_slicing_credit_cost + zero_data_retention_credit_cost, plus the billed engine and the resolved proxy tier."
    • removedOutput schema / properties / response_meta / properties / usage / properties / credits
      Removed value: -{
      -  "deprecated": true,
      -  "description": "Deprecated: use total_credit_cost, which always has the same value. This field will be removed in a future version.",
      -  "maximum": 9007199254740991,
      -  "minimum": 0,
      -  "type": "integer"
      -}
    • removedOutput schema / properties / response_meta / properties / usage / properties / screenshot_slices
      Removed value: -{
      -  "deprecated": true,
      -  "description": "Deprecated: use screenshot_slicing_credit_cost, which always has the same value. Despite its name this is a 0/1 charge, not a count of slices. This field will be removed in a future version.",
      -  "maximum": 9007199254740991,
      -  "minimum": 0,
      -  "type": "integer"
      -}
    • changedOutput schema / properties / response_meta / properties / usage / properties / screenshot_slicing_credit_cost / description
      Previous value: -"The screenshot slicing add-on: 1 when the screenshot was split into slices on this request (a flat +1 credit outside the proxy multiplier, however many slices it made), else 0. A cache hit that reused slices that already existed costs 0. Older api versions do not send it; read `screenshot_slices` then, which has the same value."New value: +"The screenshot slicing add-on: 1 when the screenshot was split into slices on this request (a flat +1 credit outside the proxy multiplier, however many slices it made), else 0. A cache hit that reused slices that already existed costs 0. Older api versions do not send it."
    • changedOutput schema / properties / response_meta / properties / usage / properties / total_credit_cost / description
      Previous value: -"Credits charged for this request. Always equals engine_credit_cost × proxy_multiplier + screenshot_slicing_credit_cost. 0 when nothing is billed: a cache hit, or a page whose status is not billed (see page_status_code). Older api versions do not send it; read `credits` then, which has the same value."New value: +"Credits charged for this request. Always equals engine_credit_cost × proxy_multiplier + screenshot_slicing_credit_cost + zero_data_retention_credit_cost. 0 when nothing is billed: a cache hit, or a page whose status is not billed (see page_status_code). Older api versions do not send it."
    • addedOutput schema / properties / response_meta / properties / usage / properties / zero_data_retention_credit_cost
      Added value: +{
      +  "description": "Credits added by zero data retention: 1 on a billed, fresh result, else 0. Older api versions do not send it.",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedOutput schema / properties / screenshot / properties / slices / items / properties / url / description
      Previous value: -"URL to download this slice image"New value: +"Signed link to download this slice image. It expires 24 hours after the scrape (for an async scrape, 24 hours after you submitted it). Download the image, do not keep the link"
    • changedOutput schema / properties / screenshot / properties / url / description
      Previous value: -"URL to download the full screenshot image"New value: +"Signed link to download the full screenshot image. It expires 24 hours after the scrape (for an async scrape, 24 hours after you submitted it). Download the image, do not keep the link"
    • changedOutput schema / properties / warnings / description
      Previous value: -"Non-error notices about the scrape. Truncation codes — `screenshot_truncated` (long page exceeded the scrolling-screenshot height cap), `links_truncated` / `inline_images_truncated` (page had more links/images than the per-page extraction caps), `raw_html_truncated` / `metadata_truncated` (rendered HTML exceeded the per-page size budget) — mean the field is present but capped. Unavailability codes — `links_unavailable` / `inline_images_unavailable` / `metadata_unavailable` — mean that optional field could not be extracted and was omitted (null/empty) while the rest of the scrape succeeded, so an empty field carrying one of these does NOT mean the page had none. Stable string codes — clients can switch on them. Warnings are stored with the result: async result fetches and cache hits carry them too, filtered to the fields the request asked for."New value: +"Non-error notices about the scrape. Truncation codes — `screenshot_truncated` (long page exceeded the scrolling-screenshot height cap), `links_truncated` / `inline_images_truncated` (page had more links/images than the per-page extraction caps), `raw_html_truncated` (rendered HTML exceeded the per-page size budget) — mean the field is present but capped. `elements_truncated` means at least one `elements` value hit a limit: a list was cut at 1,000 matches, the request reached 10,000 matches in total, or a value did not fit the ~1 MB of values allowed per request (that value is then null, never cut short). Unavailability codes — `links_unavailable` / `inline_images_unavailable` / `metadata_unavailable` — mean that optional field could not be extracted and was omitted (null/empty) while the rest of the scrape succeeded, so an empty field carrying one of these does NOT mean the page had none. `screenshot_unavailable` means a screenshot was asked for, but the page came back from the http engine without one. Stable string codes — clients can switch on them. Warnings are stored with the result: async result fetches and cache hits carry them too, filtered to the fields the request asked for. `metadata_truncated` is retired and no longer sent: metadata has no size limit of its own now, though the code can still appear on results stored before that change."
  3. Changed14 schema fields changedv1.1.0
    • addedOutput schema / properties / page_status_code
      Added value: +{
      +  "description": "The HTTP status the site answered with for the final page, after redirects. Check it before you trust the content. A page the site served is a successful result whatever its status: a 404 or 503 page comes back with its content here, not as an error, so a 404 means the markdown is the site's \"not found\" page, not the page you asked for. Billing follows this status: 2xx and 4xx pages are billed, except 403, 407, 408, 429 and 451; 5xx pages are never billed. Older api versions do not send it; they only returned pages that loaded normally.",
      +  "maximum": 9007199254740991,
      +  "minimum": -9007199254740991,
      +  "type": "integer"
      +}
    • changedOutput schema / properties / response_meta / description
      Previous value: -"Request-level metadata. `response_meta.usage` reports credits charged, the billed engine, the resolved proxy tier, and any screenshot-slice add-on."New value: +"Request-level metadata. `response_meta.usage` reports what the request cost (total_credit_cost and its parts), the billed engine and the resolved proxy tier."
    • changedOutput schema / properties / response_meta / properties / usage / description
      Previous value: -"Usage accounting for this request: credits charged, billed engine, resolved proxy tier, and screenshot-slice add-on."New value: +"What this request cost and why: total_credit_cost = engine_credit_cost × proxy_multiplier + screenshot_slicing_credit_cost, plus the billed engine and the resolved proxy tier."
    • addedOutput schema / properties / response_meta / properties / usage / properties / credits / deprecated
      Added value: +true
    • changedOutput schema / properties / response_meta / properties / usage / properties / credits / description
      Previous value: -"Credits actually charged for this request. Always equals the engine base × the proxy multiplier, plus screenshot_slices. A cache hit has engine \"cache\" (base 0), so it costs only the parts we still had to compute — a newly produced screenshot-slice variant — and is otherwise free."New value: +"Deprecated: use total_credit_cost, which always has the same value. This field will be removed in a future version."
    • changedOutput schema / properties / response_meta / properties / usage / properties / engine / description
      Previous value: -"The engine base the request was billed at — \"http\" (1 credit), \"browser\" (3), \"screenshot\" (5), or \"cache\" (0, the result was served from cache) — before the proxy multiplier. Reflects what was delivered, never what was requested."New value: +"The engine the request was billed at — \"http\", \"browser\", \"screenshot\", or \"cache\" (the result was served from cache). Reflects what was delivered, never what was requested."
    • addedOutput schema / properties / response_meta / properties / usage / properties / engine_credit_cost
      Added value: +{
      +  "description": "The engine base charged, before the proxy multiplier: 1 for \"http\", 3 for \"browser\", 5 for \"screenshot\", 0 for \"cache\". Also 0 when the page is not billed (see page_status_code). Older api versions do not send it.",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedOutput schema / properties / response_meta / properties / usage / properties / proxy / description
      Previous value: -"The proxy tier the request actually ran on (resolved value — never `auto`; `auto` is resolved server-side to `basic` or `advanced`)."New value: +"The proxy tier the request actually ran on (resolved value — never `auto`; `auto` is resolved server-side to `basic` or `advanced`). \"advanced\" multiplies the engine base by 5."
    • addedOutput schema / properties / response_meta / properties / usage / properties / proxy_multiplier
      Added value: +{
      +  "description": "The multiplier of the proxy tier the request ran on: 1 for \"basic\", 5 for \"advanced\". Always reported, even when the engine cost is 0. Older api versions do not send it.",
      +  "exclusiveMinimum": 0,
      +  "maximum": 9007199254740991,
      +  "type": "integer"
      +}
    • addedOutput schema / properties / response_meta / properties / usage / properties / screenshot_slices / deprecated
      Added value: +true
    • changedOutput schema / properties / response_meta / properties / usage / properties / screenshot_slices / description
      Previous value: -"Whether this request was billed the screenshot-split add-on: 1 when the screenshot was split on this request (a flat +1 credit outside the proxy multiplier, regardless of how many slices the split produced), else 0 — including a cache hit that reused an already-existing slice variant."New value: +"Deprecated: use screenshot_slicing_credit_cost, which always has the same value. Despite its name this is a 0/1 charge, not a count of slices. This field will be removed in a future version."
    • addedOutput schema / properties / response_meta / properties / usage / properties / screenshot_slicing_credit_cost
      Added value: +{
      +  "description": "The screenshot slicing add-on: 1 when the screenshot was split into slices on this request (a flat +1 credit outside the proxy multiplier, however many slices it made), else 0. A cache hit that reused slices that already existed costs 0. Older api versions do not send it; read `screenshot_slices` then, which has the same value.",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedOutput schema / properties / response_meta / properties / usage / properties / total_credit_cost
      Added value: +{
      +  "description": "Credits charged for this request. Always equals engine_credit_cost × proxy_multiplier + screenshot_slicing_credit_cost. 0 when nothing is billed: a cache hit, or a page whose status is not billed (see page_status_code). Older api versions do not send it; read `credits` then, which has the same value.",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedOutput schema / properties / response_meta / properties / usage / required
      Previous value: -[
      -  "credits",
      -  "engine",
      -  "proxy",
      -  "screenshot_slices"
      -]New value: +[
      +  "engine",
      +  "proxy"
      +]
  4. First observedv1.0.3

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden and does so thoroughly: it explains that 4xx/5xx pages return as content rather than errors, the exact billing matrix (403/407/408/429/451 and 5xx free), `target_unreachable` (502, unbilled), screenshot links expiring after 24h, the credit formula, and zero_data_retention's cost and org prerequisite. It also disambiguates empty fields: a warning means extraction failed and should be retried, while an empty field without a warning means the page genuinely had none — a subtlety an agent would otherwise get wrong.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the `map` alternative are front-loaded, and nearly every sentence carries operational weight (billing, truncation caps, warning semantics). It is nonetheless a dense wall of rules that partially duplicates schema descriptions of cleanup and extraction caps, costing some scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter tool with nested objects and no annotations, the description covers everything an agent needs: success vs. error framing, billing, truncation and failure warnings, cache and retention behavior, and cleanup scope. An output schema exists, yet the description still supplies the interpretive keys (`page_status_code`, `warnings`, `response_meta.usage`) needed to read it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine semantics beyond the schema: `extract.elements` as name→CSS selector returning in a top-level `elements` field at no extra credit, and the critical rule that `cleanup` shapes markdown/HTML/links/images/screenshot but never `raw_html`. It does not cover `require_js`, `proxy`, or `location` selection trade-offs, which remain schema-only.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetch a single URL via the crawlbrulee scraping API') and enumerates the returnable content formats. It also explicitly positions itself against a sibling ('For full-site discovery use the `map` tool first') and vs. multi-step workflows ('one-shot page extraction'), so an agent can pick it without reading any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear when-to-use guidance and names `map` as the alternative for site discovery, plus a concrete preference to use `extract.elements` rather than dumping full markdown. It does not, however, route against `scrape_async`/`scrape_status`/`scrape_result`, which are the most likely confusable siblings for long-running or batch work.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.