Skip to content

Extract API

Updated Feb 2026

The Extract API (/v1/extract) gathers structured data from one or more URLs using LLM-powered extraction. It handles crawling, parsing, and collating datasets -- distinct from the JSON mode on scrape which operates on a single page.

Extract vs Scrape + JSON Mode

  • Scrape + JSON Mode (/v2/scrape): Extract structured data from one URL during a scrape. See LLM Extract.
  • Extract API (/v1/extract): Extract structured data across multiple URLs, supports async operations, wildcards, web search enrichment, and the FIRE-1 agent for complex interactions.

Overview

Rate Limit: 10 requests per minute

Extraction Modes

ModeDescriptionWhen to Use
Schema-basedProvide a JSON Schema for rigid, typed outputYou know the exact structure you need
Prompt-onlyLet the LLM determine output structureExploratory extraction, flexible needs
Schema + PromptSchema for structure, prompt for guidanceMaximum control over extraction
No URLs (Alpha)Extract using only a prompt, no URLsLet the system find relevant data
FIRE-1 AgentBrowser automation for complex pagesPaginated data, dynamic elements, forms

Parameters

ParameterTypeRequiredDescription
urlsstring[]No*Target URLs; supports wildcards (e.g., https://example.com/*)
promptstringYesNatural language description of the data to extract
schemaobjectNoJSON Schema defining the output structure
enableWebSearchbooleanNoFollow external links for enriched results
agentobjectNoAgent configuration (e.g., {"model": "FIRE-1"})

*URLs are optional in Alpha mode (prompt-only extraction).

URL Patterns

python
# Single URL
urls = ["https://example.com/pricing"]

# Multiple specific URLs
urls = [
    "https://example.com/pricing",
    "https://example.com/features",
    "https://example.com/about"
]

# Wildcard (experimental) — matches all pages on the domain
urls = ["https://example.com/*"]

Wildcard Support

Wildcard URL patterns (/*) are experimental. Coverage of large sites may be incomplete, and results can vary on dynamic sites.

Basic Usage

Schema-Based Extraction

Python

python
from firecrawl import FirecrawlApp

app = FirecrawlApp(api_key="fc-YOUR-API-KEY")

result = app.extract(
    urls=["https://firecrawl.dev/pricing"],
    prompt="Extract all pricing plans with their names, prices, and included features",
    schema={
        "type": "object",
        "properties": {
            "plans": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "monthly_price": {"type": "string"},
                        "annual_price": {"type": "string"},
                        "features": {
                            "type": "array",
                            "items": {"type": "string"}
                        }
                    },
                    "required": ["name", "monthly_price"]
                }
            }
        },
        "required": ["plans"]
    }
)

for plan in result['data']['plans']:
    print(f"{plan['name']}: {plan['monthly_price']}/mo")

Node.js

javascript
import FirecrawlApp from '@mendable/firecrawl-js';

const app = new FirecrawlApp({ apiKey: "fc-YOUR-API-KEY" });

const result = await app.extract({
  urls: ["https://firecrawl.dev/pricing"],
  prompt: "Extract all pricing plans with their names, prices, and included features",
  schema: {
    type: "object",
    properties: {
      plans: {
        type: "array",
        items: {
          type: "object",
          properties: {
            name: { type: "string" },
            monthly_price: { type: "string" },
            annual_price: { type: "string" },
            features: { type: "array", items: { type: "string" } }
          },
          required: ["name", "monthly_price"]
        }
      }
    },
    required: ["plans"]
  }
});

console.log(result.data);

cURL

bash
curl -X POST https://api.firecrawl.dev/v1/extract \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer fc-YOUR-API-KEY' \
  -d '{
    "urls": ["https://firecrawl.dev/pricing"],
    "prompt": "Extract all pricing plans with their names, prices, and included features",
    "schema": {
      "type": "object",
      "properties": {
        "plans": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": {"type": "string"},
              "monthly_price": {"type": "string"},
              "features": {"type": "array", "items": {"type": "string"}}
            },
            "required": ["name", "monthly_price"]
          }
        }
      },
      "required": ["plans"]
    }
  }'

Prompt-Only Extraction

Let the LLM decide the output structure:

python
result = app.extract(
    urls=["https://firecrawl.dev"],
    prompt="Extract all information about the company's products, pricing, and team"
)

print(result['data'])
# Structure determined by the LLM based on page content
javascript
const result = await app.extract({
  urls: ["https://firecrawl.dev"],
  prompt: "Extract all information about the company's products, pricing, and team"
});

With Web Search Enrichment

Follow external links to gather additional context:

python
result = app.extract(
    urls=["https://example.com/company"],
    prompt="Extract company information and recent funding details",
    schema={
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "founded": {"type": "string"},
            "funding": {"type": "string"},
            "investors": {"type": "array", "items": {"type": "string"}}
        }
    },
    enableWebSearch=True  # Follow links for enrichment
)

With FIRE-1 Agent

For pages requiring browser interaction:

python
result = app.extract(
    urls=["https://example.com/products"],
    prompt="Navigate through all pagination pages and extract every product name, price, and rating",
    schema={
        "type": "object",
        "properties": {
            "products": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "price": {"type": "string"},
                        "rating": {"type": "number"}
                    }
                }
            }
        }
    },
    agent={"model": "FIRE-1"}
)

See FIRE-1 Agent Model for full documentation.

Async Operations

For long-running extractions, use the start/poll pattern:

Python

python
# Start the extraction job (returns immediately)
job = app.start_extract(
    urls=["https://example.com/*"],
    prompt="Extract all product information from the site",
    schema={...}
)

print(f"Job ID: {job['id']}")

# Poll for status
import time

while True:
    status = app.get_extract_status(job['id'])
    print(f"Status: {status['status']}")

    if status['status'] == 'completed':
        print(status['data'])
        break
    elif status['status'] == 'failed':
        print(f"Error: {status.get('error')}")
        break

    time.sleep(5)

Node.js

javascript
// Start the extraction job
const job = await app.startExtract({
  urls: ["https://example.com/*"],
  prompt: "Extract all product information from the site",
  schema: {...}
});

console.log(`Job ID: ${job.id}`);

// Poll for status
let status;
do {
  await new Promise(resolve => setTimeout(resolve, 5000));
  status = await app.getExtractStatus(job.id);
  console.log(`Status: ${status.status}`);
} while (status.status === 'processing');

if (status.status === 'completed') {
  console.log(status.data);
}

cURL

bash
# Start extraction
curl -X POST https://api.firecrawl.dev/v1/extract \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer fc-YOUR-API-KEY' \
  -d '{
    "urls": ["https://example.com/*"],
    "prompt": "Extract all product information",
    "schema": {...}
  }'

# Response: {"success": true, "id": "extract-abc123"}

# Check status
curl -X GET https://api.firecrawl.dev/v1/extract/extract-abc123 \
  -H 'Authorization: Bearer fc-YOUR-API-KEY'

Job Status Values

StatusDescription
processingJob is running
completedResults are ready
failedJob encountered an error
cancelledJob was cancelled

Results are accessible for 24 hours after completion.

Response Format

json
{
  "success": true,
  "data": {
    "plans": [
      {
        "name": "Free",
        "monthly_price": "$0",
        "features": ["500 credits", "5 agent runs/day"]
      },
      {
        "name": "Starter",
        "monthly_price": "$19",
        "features": ["3,000 credits", "Batch scrape", "Priority support"]
      }
    ]
  }
}

Extract vs Agent API

FeatureExtract (/v1/extract)Agent (/v2/agent)
PurposeStructured extraction from known URLsAutonomous research
URLsRequired (or wildcard)Optional
Web SearchOptional (enableWebSearch)Built-in
Browser AgentFIRE-1 (optional)Spark-1 Mini/Pro
OutputSchema-defined JSONSchema or unstructured
Best ForTargeted data collectionOpen-ended research

When to Use Which

  • Known URLs, need structured data --> Extract API
  • Don't know where the data is --> Agent API
  • Single page, simple extraction --> Scrape + JSON mode
  • Complex page interactions needed --> Extract API + FIRE-1

Pricing

Extract API uses a unified credit system where each credit equals approximately 15 tokens. Costs vary based on:

  • Number of URLs processed
  • Prompt complexity
  • Schema size
  • Data volume in responses
  • FIRE-1 agent usage (if enabled)

See Pricing for full details.

Limitations (Beta)

The Extract API is in beta. Current limitations:

  • Large sites: Full coverage of massive sites with wildcards may be incomplete
  • Complex queries: Highly complex logical queries may produce inconsistent results
  • Dynamic sites: Results may vary on frequently updated or JavaScript-heavy sites
  • Rate limit: 10 requests per minute

Next: Features Overview -->