Appearance
Choosing the Right Data Extractor
Updated Feb 2026Firecrawl 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 Knowledge | Optional -- can discover URLs autonomously | Required | Required |
| Scope | Web-wide discovery across multiple sites | Multiple pages on known domains | Single page |
| Processing | Async (poll for results) | Async (poll for results) | Sync (immediate response) |
| Cost | Dynamic / 5 free daily runs | Token-based (1 credit = 15 tokens) | 1 credit per page |
| Best For | Research and discovery | Known multi-page tasks | Precise 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) orspark-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 contentDecision 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 /scrapeScenario-Based Recommendations
| Task | Recommended | Why |
|---|---|---|
| Industry research without known sources | /agent | Discovers sources autonomously |
| Extract data from a specific product page | /scrape (JSON mode) | 1 credit, synchronous, precise |
| Monitor 50 known competitor URLs | Batch /scrape | Predictable cost, parallel processing |
| Find contact info from an industry directory | /agent | Navigates 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 hint | Agent explores the site structure |
| Extract data from a single known PDF or doc | /scrape | Handles document parsing natively |
Pricing Comparison
Cost Per Operation
| Extractor | Pricing Model | Predictability |
|---|---|---|
/scrape | 1 credit per page | High -- always 1 credit |
/extract | Token-based (1 credit = 15 tokens) | Medium -- varies by page size |
/agent | Dynamic, complexity-based; 5 free daily | Low -- depends on discovery steps |
Example: "Find Firecrawl's founders"
| Method | Credits | Notes |
|---|---|---|
/scrape the about page | ~1 credit | You must already know the URL |
/extract with domain wildcard | Variable | Token cost depends on pages crawled |
/agent with prompt only | ~100-500 credits | Discovers 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 When | Use JSON Mode When |
|---|---|
| Feeding content to an LLM for summarization | You need specific fields (price, title, rating) |
| Building a RAG knowledge base | Data goes into a database or spreadsheet |
| Content is unstructured (blog posts, articles) | Data has a consistent, repeatable structure |
| You want the full page context | You 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
- Maximum cost efficiency: Choose
/scrapewith JSON mode when URLs are known - Autonomous capability:
/agenteliminates manual URL discovery at a higher credit cost - Future direction:
/extractis being superseded by/agent-- use/agentfor new projects - Format choice matters: Use JSON mode for structured data, markdown for content that needs LLM processing
- Batch when possible: Use
batchScrapeUrlsinstead of sequential scrapes for multiple known URLs