Skip to main content
Glama
CrawlForge MCP Server

CrawlForge MCP Server

extract_structured

Read-onlyIdempotent

Use this to get a specific data shape from a page using a JSON schema when you can describe the fields but not their selectors - product details, job listings, event data.

Instructions

Use this to get a specific data shape from a page using a JSON schema when you can describe the fields but not their selectors - product details, job listings, event data. Uses an LLM by default; falls back to CSS selectors when no LLM is configured. Not for pages with stable markup whose selectors you know (scrape_structured, no LLM, cheaper). Asking again for the same page with different formats, paths or selectors reuses this session's copy for 10 minutes at 1 credit; pass maxAge: 0 to force a fresh fetch. Cost: 3 credits. Example: extract_structured({url: "https://jobs.example.com/post/123", schema: {properties: {title: {type:"string"}, salary: {type:"string"}}, required:["title"]}})

Input Schema

NameRequiredDescriptionDefault
urlYesThe URL to extract structured data from
maxAgeNoReuse this session's copy of the page if it was fetched within this many ms (default 600000 = 10 min); 0 always fetches fresh.
promptNoNatural language instructions for extraction
schemaYesJSON schema defining the data structure to extract
llmConfigNoLLM provider configuration for AI-powered extraction
user_agentNoOverride the outbound User-Agent. CrawlForge identifies itself honestly by default; use this only for targets you have your own agreement with.
selectorHintsNoCSS selector hints to guide extraction
respect_robotsNoRespect the target site's robots.txt (default: true). Setting this to false is honoured, returns a warning in the response, and is recorded against your API key — it is your decision, not a silent default.
verify_numbersNoNumeric provenance guard (default: true): every price or numeric value the LLM returns must appear literally in the page source, else it is returned as null with a reason in `provenance.unverified`. Set false to get the model's raw numbers back, including ones it derived (a count, a sum, a total) rather than read off the page.
fallbackToSelectorsNoFall back to CSS selector extraction if LLM is unavailable

Output Schema

NameRequiredDescriptionDefault
urlNo
dataNoExtracted fields matching the requested schema; every requested field is present, null when not found
_costNoCost-transparency metadata (D3.5): what this call was projected to cost and what it was charged
cacheNoPage cache: whether this call reused a copy of the page fetched earlier in the session
errorNo
modelNoModel that produced the data, e.g. "gemma3:12b"; present when extraction_method is "llm"
successNoFalse when the extraction errored, or a required field came back missing, empty, or in the wrong shape
providerNoLLM provider that produced the data ("ollama" | "openai" | "anthropic"); present when extraction_method is "llm"
next_stepNoFailed calls only: the tool or fix to try next
confidenceNo0-1: method and validation, scaled by the share of requested fields filled and, for "llm", the share of short string values found in the page
provenanceNo
validationNo
schema_usedNo
missing_fieldsNoRequested schema fields no extraction method found on the page; each is present in data as null
processingTimeNo
extractionNotesNo
extraction_methodNo"llm" | "css_fallback" | "keyword_fallback" | "none"

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed7 schema fields changedv6.24.0
    • addedInput schema / properties / maxAge
      Added value: +{
      +  "description": "Reuse this session's copy of the page if it was fetched within this many ms (default 600000 = 10 min); 0 always fetches fresh.",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedOutput schema / properties / _cost / description
      Previous value: -"Cost-transparency metadata (D3.5), present when injected into the text copy of the result"New value: +"Cost-transparency metadata (D3.5): what this call was projected to cost and what it was charged"
    • changedOutput schema / properties / _cost / properties / actual / description
      Previous value: -"Credits actually charged (0 in creator mode, half-rate on error)"New value: +"Credits actually charged (0 in creator mode, and 0 for a failed call)"
    • addedOutput schema / properties / cache
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Page cache: whether this call reused a copy of the page fetched earlier in the session",
      +  "properties": {
      +    "ageMs": {
      +      "description": "Age of that copy in ms",
      +      "type": [
      +        "number",
      +        "null"
      +      ]
      +    },
      +    "fetchedAt": {
      +      "description": "When the oldest page used was fetched (ISO 8601)",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "note": {
      +      "description": "Hits only: how old the copy is and how to force a fresh fetch",
      +      "type": "string"
      +    },
      +    "state": {
      +      "description": "hit: every page came from this session's copy; bypass: fetched fresh on request (maxAge 0) or not cacheable; miss: fetched",
      +      "enum": [
      +        "hit",
      +        "miss",
      +        "bypass"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
    • changedOutput schema / properties / data / description
      Previous value: -"Extracted fields matching the requested schema"New value: +"Extracted fields matching the requested schema; every requested field is present, null when not found"
    • addedOutput schema / properties / missing_fields
      Added value: +{
      +  "description": "Requested schema fields no extraction method found on the page; each is present in data as null",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / next_step
      Added value: +{
      +  "description": "Failed calls only: the tool or fix to try next",
      +  "type": "string"
      +}
  2. Changed5 schema fields changedv6.19.2
    • addedOutput schema / properties / confidence / description
      Added value: +"0-1: method and validation, scaled by the share of requested fields filled and, for \"llm\", the share of short string values found in the page"
    • addedOutput schema / properties / model
      Added value: +{
      +  "description": "Model that produced the data, e.g. \"gemma3:12b\"; present when extraction_method is \"llm\"",
      +  "type": "string"
      +}
    • changedOutput schema / properties / provenance / properties / nulled / description
      Previous value: -"Numeric values replaced with null because the source does not contain them"New value: +"Values replaced with null: numbers the source does not contain, and string fields whose value cannot be what the field names"
    • changedOutput schema / properties / provenance / properties / unverified / items / properties / reason / description
      Previous value: -"\"not_found_in_source\""New value: +"\"not_found_in_source\" | \"not_a_version\" (a version field with no number, e.g. \"latest\") | \"not_an_identifier\" (a sku/isbn/gtin/upc/ean/mpn field holding a phrase)"
    • addedOutput schema / properties / provider
      Added value: +{
      +  "description": "LLM provider that produced the data (\"ollama\" | \"openai\" | \"anthropic\"); present when extraction_method is \"llm\"",
      +  "type": "string"
      +}
  3. Changed1 schema field changedv6.5.0
    • changedOutput schema / properties / success / description
      Previous value: -"False when the extraction errored or a required field came back missing or empty"New value: +"False when the extraction errored, or a required field came back missing, empty, or in the wrong shape"
  4. Changed11 schema fields changedv6.0.0
    • removedInput schema / additionalProperties
      Removed value: -false
    • removedInput schema / properties / llmConfig / additionalProperties
      Removed value: -false
    • removedInput schema / properties / schema / additionalProperties
      Removed value: -false
    • addedInput schema / properties / schema / properties / properties / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • addedInput schema / properties / selectorHints / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / properties / _cost / additionalProperties
      Previous value: -trueNew value: +{}
    • addedOutput schema / properties / data / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / properties / provenance / additionalProperties
      Previous value: -trueNew value: +{}
    • changedOutput schema / properties / provenance / properties / unverified / items / additionalProperties
      Previous value: -trueNew value: +{}
    • addedOutput schema / properties / schema_used / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / properties / validation / additionalProperties
      Previous value: -trueNew value: +{}
  5. Changed5 schema fields changedv5.4.0
    • addedInput schema / properties / respect_robots
      Added value: +{
      +  "description": "Respect the target site's robots.txt (default: true). Setting this to false is honoured, returns a warning in the response, and is recorded against your API key — it is your decision, not a silent default.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / user_agent
      Added value: +{
      +  "description": "Override the outbound User-Agent. CrawlForge identifies itself honestly by default; use this only for targets you have your own agreement with.",
      +  "type": "string"
      +}
    • addedInput schema / properties / verify_numbers
      Added value: +{
      +  "default": true,
      +  "description": "Numeric provenance guard (default: true): every price or numeric value the LLM returns must appear literally in the page source, else it is returned as null with a reason in `provenance.unverified`. Set false to get the model's raw numbers back, including ones it derived (a count, a sum, a total) rather than read off the page.",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / provenance
      Added value: +{
      +  "additionalProperties": true,
      +  "properties": {
      +    "enabled": {
      +      "description": "Whether the numeric provenance guard ran",
      +      "type": "boolean"
      +    },
      +    "nulled": {
      +      "description": "Numeric values replaced with null because the source does not contain them",
      +      "type": "number"
      +    },
      +    "skipped": {
      +      "description": "\"empty_source\" when there was nothing to check against",
      +      "type": "string"
      +    },
      +    "unverified": {
      +      "items": {
      +        "additionalProperties": true,
      +        "properties": {
      +          "path": {
      +            "description": "Path to the field, e.g. configurations[2].price",
      +            "type": "string"
      +          },
      +          "reason": {
      +            "description": "\"not_found_in_source\"",
      +            "type": "string"
      +          },
      +          "value": {
      +            "description": "The value that was removed"
      +          }
      +        },
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "verified": {
      +      "description": "Numeric values found literally in the page source",
      +      "type": "number"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / success
      Added value: +{
      +  "description": "False when the extraction errored or a required field came back missing or empty",
      +  "type": "boolean"
      +}
  6. Changed1 schema field changedv5.1.0
    • changedOutput schema / properties / extraction_method / description
      Previous value: -"\"llm\" | \"css_fallback\" | \"none\""New value: +"\"llm\" | \"css_fallback\" | \"keyword_fallback\" | \"none\""
  7. Changed2 schema fields changedv5.0.4
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "https://json-schema.org/draft/2020-12/schema",
      +  "additionalProperties": false,
      +  "properties": {
      +    "_cost": {
      +      "additionalProperties": true,
      +      "description": "Cost-transparency metadata (D3.5), present when injected into the text copy of the result",
      +      "properties": {
      +        "actual": {
      +          "description": "Credits actually charged (0 in creator mode, half-rate on error)",
      +          "type": "number"
      +        },
      +        "projected": {
      +          "description": "Credits projected for this call before execution",
      +          "type": "number"
      +        },
      +        "projection_note": {
      +          "description": "Human-readable note about how the cost was projected",
      +          "type": "string"
      +        },
      +        "remaining_credits": {
      +          "description": "Credits remaining on the account after this call, if known",
      +          "type": [
      +            "number",
      +            "null"
      +          ]
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "confidence": {
      +      "type": "number"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "description": "Extracted fields matching the requested schema",
      +      "type": "object"
      +    },
      +    "error": {
      +      "type": "string"
      +    },
      +    "extractionNotes": {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "extraction_method": {
      +      "description": "\"llm\" | \"css_fallback\" | \"none\"",
      +      "type": "string"
      +    },
      +    "processingTime": {
      +      "type": "number"
      +    },
      +    "schema_used": {
      +      "additionalProperties": {},
      +      "type": "object"
      +    },
      +    "url": {
      +      "type": "string"
      +    },
      +    "validation": {
      +      "additionalProperties": true,
      +      "properties": {
      +        "errors": {
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        },
      +        "valid": {
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    }
      +  },
      +  "type": "object"
      +}
  8. First observedv4.10.0

TDQS

A4.9/5.0
Behavior5/5

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

Although annotations already declare readOnly, idempotent, openWorld, and non-destructive behavior, the description adds material context: LLM default with CSS fallback, session reuse for 10 minutes at 1 credit, maxAge override, and a 3-credit cost. This is substantially more than the annotations provide.

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

Conciseness5/5

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

The description is dense but front-loaded: use case, mechanism, exclusion, caching/cost, and example. Every sentence adds decision-relevant information, and the example is compact enough to be useful without dominating.

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 a full input schema, output schema, and rich annotations, the description supplies the remaining decision-critical context: when to choose this over sibling tools, LLM fallback behavior, caching semantics, and cost. Nothing essential for correct invocation 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 schema carries most parameter meaning. The description still adds useful semantics for maxAge caching behavior and a concrete schema example; advanced parameters such as verify_numbers and respect_robots are left to the well-documented schema.

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 (extract structured data), resource (page), and mechanism (JSON schema when selectors are unknown). It explicitly distinguishes from scrape_structured, making sibling selection straightforward.

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 context ('describe the fields but not their selectors') and when-not-to-use guidance ('stable markup whose selectors you know'), naming the cheaper alternative scrape_structured.

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