Skip to content

Choosing the Right Data Extractor

Updated Feb 2026

Firecrawl provides three primary extraction approaches, each optimized for different scenarios. This guide helps you choose the right one based on your use case, budget, and data requirements.

Quick Comparison

Aspect/agent/extract/scrape (JSON mode)
URL KnowledgeOptional -- can discover URLs autonomouslyRequiredRequired
ScopeWeb-wide discovery across multiple sitesMultiple pages on known domainsSingle page
ProcessingAsync (poll for results)Async (poll for results)Sync (immediate response)
CostDynamic / 5 free daily runsToken-based (1 credit = 15 tokens)1 credit per page
Best ForResearch and discoveryKnown multi-page tasksPrecise single-page extraction

The Three Extractors

1. /agent -- Autonomous Web Discovery

The most powerful option. AI agents search, navigate, and extract data from across the web independently. You describe what you need in a prompt -- URLs are optional.

Key strengths:

  • No URL required -- the agent discovers sources on its own
  • Parallel processing across multiple sites
  • Two model options: spark-1-mini (faster, cheaper) or spark-1-pro (higher accuracy)

Ideal scenario: Finding Series A AI startups when you do not know which websites host this data.

typescript
import FirecrawlApp from "@mendable/firecrawl-js";
import { z } from "zod";

const app = new FirecrawlApp({ apiKey: process.env.FIRECRAWL_API_KEY });

const startupSchema = z.object({
  companyName: z.string(),
  fundingRound: z.string(),
  amount: z.string(),
  investors: z.array(z.string()),
  website: z.string(),
});

// No URLs needed -- the agent finds the data
const result = await app.agent({
  prompt: "Find 5 AI startups that raised Series A in the last 3 months",
  schema: startupSchema,
  model: "spark-1-mini",
});

console.log(result.data);

2. /extract -- Multi-URL Structured Extraction

Structured data collection from specified domains or URL patterns. Supports domain crawling and wildcard patterns.

WARNING

Firecrawl recommends using /agent instead of /extract for new projects. The /agent endpoint is the preferred path forward.

Strengths:

  • Supports domain-level crawling with wildcard URL patterns
  • Optional web search enhancement for external links
  • Flexible schema support

Limitation: Requires knowing URLs upfront.

typescript
const result = await app.extract({
  urls: ["https://example.com/*"],
  prompt: "Extract all product names and prices",
  schema: productSchema,
});

3. /scrape with JSON Mode -- Single-Page Precision

The most controlled and cost-effective approach. Extract structured data from one known page with synchronous results.

Key features:

  • Synchronous -- no polling required, results return immediately
  • Optional Zod/JSON schema validation
  • Combine JSON extraction with markdown, HTML, screenshots in the same call
  • 1 credit per page -- the most predictable cost

Ideal scenario: Price monitoring tools targeting specific product pages.

typescript
const result = await app.scrapeUrl(
  "https://example.com/product/12345",
  {
    formats: ["json", "markdown"],
    jsonOptions: {
      schema: z.object({
        title: z.string(),
        price: z.string(),
        rating: z.string(),
        availability: z.string(),
      }),
    },
  }
);

// Immediate response -- no polling
console.log(result.json);     // Structured data
console.log(result.markdown); // Full page content

Decision Tree

Use this flowchart to select the right extractor:

Do you know the exact URL(s)?
├── NO ──────────────────────> Use /agent

├── YES, single page? ──────> Use /scrape with JSON mode

└── YES, multiple pages?
    ├── Need discovery? ────> Use /agent (with URLs as hints)
    └── Just extraction? ──> Use batch /scrape

Scenario-Based Recommendations

TaskRecommendedWhy
Industry research without known sources/agentDiscovers sources autonomously
Extract data from a specific product page/scrape (JSON mode)1 credit, synchronous, precise
Monitor 50 known competitor URLsBatch /scrapePredictable cost, parallel processing
Find contact info from an industry directory/agentNavigates complex multi-page layouts
Daily price tracking on known pages/scrape (JSON mode)Cheapest per-page, reliable for recurring jobs
Build a dataset from an unknown domain/agent with URL hintAgent explores the site structure
Extract data from a single known PDF or doc/scrapeHandles document parsing natively

Pricing Comparison

Cost Per Operation

ExtractorPricing ModelPredictability
/scrape1 credit per pageHigh -- always 1 credit
/extractToken-based (1 credit = 15 tokens)Medium -- varies by page size
/agentDynamic, complexity-based; 5 free dailyLow -- depends on discovery steps

Example: "Find Firecrawl's founders"

MethodCreditsNotes
/scrape the about page~1 creditYou must already know the URL
/extract with domain wildcardVariableToken cost depends on pages crawled
/agent with prompt only~100-500 creditsDiscovers the right page autonomously

The tradeoff is clear: /scrape is cheapest when you know what to target, while /agent costs more but eliminates the need for manual URL discovery.

Migration from /extract to /agent

For existing /extract users, transitioning to /agent requires minimal changes:

Before:

python
result = app.extract(
    urls=["https://example.com/*"],
    prompt="Extract all team members and their roles",
    schema=team_schema,
)

After:

python
result = app.agent(
    urls=["https://example.com"],  # Optional hint
    prompt="Extract all team members and their roles",
    schema=team_schema,
    model="spark-1-mini",
)

The key advantage: URLs become optional. The agent can find the data even without URL hints.

When to Use Markdown Parsing Instead of JSON Mode

Not every extraction needs a schema. Sometimes raw markdown is better:

Use Markdown WhenUse JSON Mode When
Feeding content to an LLM for summarizationYou need specific fields (price, title, rating)
Building a RAG knowledge baseData goes into a database or spreadsheet
Content is unstructured (blog posts, articles)Data has a consistent, repeatable structure
You want the full page contextYou only need a subset of the page data

Markdown example:

typescript
const result = await app.scrapeUrl("https://example.com/blog/post", {
  formats: ["markdown"],
});

// Feed to LLM
const summary = await llm.chat({
  messages: [
    { role: "system", content: "Summarize this article in 3 bullet points." },
    { role: "user", content: result.markdown },
  ],
});

JSON mode example:

typescript
const result = await app.scrapeUrl("https://example.com/product/123", {
  formats: ["json"],
  jsonOptions: {
    schema: z.object({
      title: z.string(),
      price: z.string(),
      inStock: z.boolean(),
    }),
  },
});

// Insert directly into database
await db.products.insert(result.json);

Key Takeaways

  1. Maximum cost efficiency: Choose /scrape with JSON mode when URLs are known
  2. Autonomous capability: /agent eliminates manual URL discovery at a higher credit cost
  3. Future direction: /extract is being superseded by /agent -- use /agent for new projects
  4. Format choice matters: Use JSON mode for structured data, markdown for content that needs LLM processing
  5. Batch when possible: Use batchScrapeUrls instead of sequential scrapes for multiple known URLs

Resources