Skip to main content
Glama

crawl_create

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. Set webhook to have signed events posted to your https URL when the crawl starts and when it ends; the account needs a webhook signing key, else CRAWL_INVALID_REQUEST (webhook_signing_key_required).

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

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.
webhookNoWhere to post the crawl's signed events (crawl.started, then one of crawl.completed, crawl.stopped, crawl.failed). Each is signed with the account's webhook signing key, in the X-Signature header.
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. Changed1 schema field changed
    • addedInput schema / properties / webhook
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": false,
      +      "properties": {
      +        "events": {
      +          "anyOf": [
      +            {
      +              "items": {
      +                "enum": [
      +                  "crawl.started",
      +                  "crawl.completed",
      +                  "crawl.stopped",
      +                  "crawl.failed"
      +                ],
      +                "type": "string"
      +              },
      +              "minItems": 1,
      +              "type": "array"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ],
      +          "description": "Events to send, each once. Omit for all four."
      +        },
      +        "metadata": {
      +          "anyOf": [
      +            {
      +              "additionalProperties": {},
      +              "propertyNames": {
      +                "maxLength": 64,
      +                "minLength": 1
      +              },
      +              "type": "object"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ],
      +          "description": "Sent back with every event, to match it to your records. Up to 20 keys of 1-64 characters, each value at most 1,024 bytes as JSON."
      +        },
      +        "url": {
      +          "description": "Absolute https URL each event is posted to",
      +          "format": "uri",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "url"
      +      ],
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Where to post the crawl's signed events (crawl.started, then one of crawl.completed, crawl.stopped, crawl.failed). Each is signed with the account's webhook signing key, in the X-Signature header."
      +}
  2. Changed3 schema fields changed
    • 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."
  3. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only cover readOnly/destructive/openWorld; the description adds billing semantics (one page = one scrape, the start page is billed even if nothing matches), default limits, and non-obvious failure modes (empty crawl ends 'completed' with no results rather than erroring). It also discloses the async nature and the required sequence crawl_wait then crawl_results, plus idempotency behavior.

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?

Core behavior, billing, and the semantics of depth are front-loaded, and most sentences carry new information. There is some redundancy — the 'no depth limit when depth is omitted' rule is stated once up front and again mid-paragraph — and the block is long, but its length is largely justified by ten parameters and four error conditions.

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?

With no output schema, the description still summarizes the return ('crawl_id, status and the crawl (with coverage)'), explains the job runs asynchronously, and points to crawl_wait and crawl_results. Combined with the cost model, edge cases, and error handling, an agent has everything needed to invoke and follow up 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; the description still earns above baseline by tying parameters to consequences — max_pages is a cost bound, include/exclude patterns should be checked against what the start page links to, output_format pairs with crawl_content, and webhook requires an account signing key or the call fails with a specific error.

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') and immediately names the scope constraints (link following, depth hops, pattern filtering, registrable-domain confinement). It explicitly contrasts with the sibling 'scrape' for single pages, so an agent can pick between them without reading either 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 a concrete when-to-use scenario ('one start page — a listing, category, blog index — and need the URLs behind it'), names the alternative tool for the other case ('For a single page, use scrape'), and adds cost-driven guidance ('set max_pages to what you are willing to spend'). Error codes come with explicit retry/no-retry instructions.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.