Skip to main content
Glama
ZenRows
by ZenRows

crawl_create

Crawl a start URL and follow its links up to a depth, keeping only URLs that match your include and exclude patterns. Returns crawl_id for asynchronous results; set max_pages to bound billing.

Instructions

Start a crawl from one URL (Zenrows Crawl API). Crawl follows the links in each page's HTML up to depth hops (no depth limit when depth is omitted), keeps the URLs that match include_patterns / exclude_patterns, and stays on the start URL's registrable domain (subdomains count).

Use crawl when you have one start page (a listing, category, blog index) and need the URLs behind it, optionally with each page's HTML. For a single page, use scrape.

Each page fetched is billed as one scrape on this account; max_pages bounds the cost (default 100), max_items bounds how many URLs are kept (default 100). Without depth, the crawl keeps following links until max_pages or max_items stops it or nothing is left to open, so set max_pages to what you are willing to spend. The start page itself is never a result, but its fetch is billed: a crawl whose include_patterns / exclude_patterns match nothing still costs that one scrape. A crawl whose pages held nothing new to follow (no link, only links to other sites, or only links the patterns reject) ends completed with no results and no error. When patterns are set, check them against the URLs the start page links to. Set output_format "html" or "markdown" to also store each kept URL's page, then read it with crawl_content.

Returns crawl_id, status and the crawl (with coverage) at once; the crawl runs asynchronously. Call crawl_wait, then crawl_results. Set idempotency_key to make a retry safe: the same key returns the crawl the first request created instead of starting another. CRAWL_NOT_ENABLED: Crawl is not enabled for this account; do not retry. CRAWL_TOO_MANY_CRAWLS: the account has reached its limit of active jobs (3 by default), shared with its Batch jobs; retry after retry_after seconds.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesStart URL: a public http(s) page, such as a listing or category page
depthNoLink hops to follow from the start URL. 1 returns the start page's links; 2 also opens those. Omit for no depth limit: the crawl follows links until max_pages or max_items stops it.
discoveryNoHow the crawl finds the URLs it follows on each page it walks. ['links'] follows the links in each page's HTML, and is what a crawl runs with when you omit this.
max_itemsNoStop once this many URLs are kept (default 100)
max_pagesNoStop once this many pages are fetched, each billed as one scrape (default 100). With output_format, every kept URL's page counts too.
output_formatNo'html' or 'markdown' also stores each kept URL's page for crawl_content, as fetched or converted to Markdown. Omit for URLs only.
idempotency_keyNoSent as the Idempotency-Key header. Reusing a key returns the crawl it created; reusing it with a different body is CRAWL_INVALID_REQUEST.
exclude_patternsNoDrop URLs containing any of these substrings, even if they match include_patterns
include_patternsNoKeep only URLs containing at least one of these substrings, e.g. ["/product/"]

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changedv2.10.2
    • addedInput schema / properties / discovery
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "enum": [
      +          "links"
      +        ],
      +        "type": "string"
      +      },
      +      "minItems": 1,
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "How the crawl finds the URLs it follows on each page it walks. ['links'] follows the links in each page's HTML, and is what a crawl runs with when you omit this."
      +}
    • changedInput schema / properties / output_format / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "html"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "html",
      +      "markdown"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / output_format / description
      Previous value: -"'html' also stores each kept URL's page for crawl_content. Omit for URLs only."New value: +"'html' or 'markdown' also stores each kept URL's page for crawl_content, as fetched or converted to Markdown. Omit for URLs only."
  2. Addedv2.7.0

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only cover the read/write/open-world profile; the description adds the cost model ('Each page fetched is billed as one scrape'), the defaults (max_pages/max_items=100), non-obvious edge cases (start page never a result but still billed; a crawl matching nothing still costs one scrape; empty crawls end completed with no error), and two named failure codes with recovery guidance — far beyond the structured fields.

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?

Long but dense and front-loaded: the core purpose and cost warning come first, error codes last. Nearly every sentence carries operational information, though the billing/cost points are restated more than once and could be tightened.

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 async, mutable, open-world tool with no output schema, the description supplies return shape (crawl_id, status, crawl with coverage), the async follow-up chain (crawl_wait → crawl_results), and the error-code table. Nothing an agent needs to invoke it correctly is missing.

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. The description still adds real semantic value: the cost implication of max_pages, the interaction between output_format and crawl_content, and the retry contract for idempotency_key. It does not, however, add anything for parameters the schema leaves thin (discovery, include/exclude syntax).

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 ('Start a crawl from one URL'), then precisely describes the mechanism: depth hops, pattern filtering, registrable-domain confinement. It explicitly names the sibling it is not ('For a single page, use scrape'), so an agent can distinguish it without opening another schema.

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

Usage Guidelines5/5

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

Gives explicit when-to-use ('one start page — a listing, category, blog index — and need the URLs behind it'), the alternative ('scrape' for a single page), and the follow-up workflow ('Call crawl_wait, then crawl_results'). Exclusions and the pattern-checking advice ('check them against the URLs the start page links to') are also present.

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