Firecrawl Credits Explained: JSON Extraction Costs
By :
Simar
July 30, 2026

⚡ Quick Answer: Firecrawl’s JSON extraction costs 5 credits per page — 1 base credit plus 4 additional credits for the LLM call. That number is not on the pricing page. It is one line inside the scrape documentation. Seven other features carry the same +4 surcharge, one carries +1, and PDFs bill per PDF page.
On the $99 Standard plan (100,000 credits), plain scraping costs $0.99 per 1,000 pages, but JSON extraction costs $4.95 per 1,000 pages.
That is a 5x difference nobody prices for, and three of Firecrawl’s billing behaviours run in the opposite direction to what you would assume — including caching, which saves time but not a single credit.
This piece is narrower and more useful. It is about the bill.
Last month I was forecasting spend for a structured-extraction build — pulling schema’d data out of a few thousand affiliate network pages — and I could not make the arithmetic work. The pricing page said 1 credit per page. My credit balance said otherwise.
So I stopped guessing and went through the documentation properly. Not the pricing page. The actual docs, endpoint by endpoint. What I found is that Firecrawl’s real credit model is complete, precise and correct — and scattered across at least six separate pages, none of them the one everybody reads.
Nobody has assembled it in one place. So here it is.
The Pricing Page Is Not Wrong. It Is Incomplete!

Open firecrawl.dev/pricing and the credit table gives you six lines:
- Scrape, Crawl, Map, Monitor — 1 credit per page
- Search — 2 credits per 10 results
- Interact — 2 credits per browser minute
That is the entire table. Extraction is absent from it.
Scroll to the FAQ and you get the acknowledgement, in one sentence with no numbers attached:

“Advanced features (JSON format, Enhanced Mode, etc.) cost additional credits.”
Etc. is doing a lot of work in that sentence. The actual figure lives in the scrape docs, stated plainly:
“JSON mode costs 4 additional credits per page”
There it is. Five credits per page, not one. And once you know the surcharge exists, you find that seven other things carry exactly the same one.
The Complete Firecrawl Credit Table

This is the reconstruction. Every figure is from Firecrawl’s own documentation, gathered from the scrape reference, the API reference, the proxies page, the lockdown page and the extractor guide.
| Operation | Credits | Where it is documented |
|---|---|---|
| Scrape / Crawl / Map / Monitor | 1 per page | Pricing page |
| Search | 2 per 10 results | Pricing page |
| Interact | 2 per browser minute | Pricing page |
| JSON format | +4 per page (5 total) | /features/scrape |
| Question format | +4 per page (5 total) | /features/scrape |
| Highlights format | +4 per page (5 total) | /features/scrape |
| Audio format | +4 per page (5 total) | /features/scrape |
| Video format | +4 per page (5 total) | /features/scrape |
| Enhanced proxy | +4 per page (5 total) | /features/proxies |
| PII redaction | +4 per page (5 total) | /features/scrape |
| Zero Data Retention | +1 per page (2 total) | /features/scrape |
| PDF parsing | 1 credit per PDF page | /features/scrape |
| Lockdown Mode — cache hit | 5 credits | /features/lockdown |
| Lockdown Mode — cache miss | 1 credit | /features/lockdown |
| /extract (deprecated) | Credit-based, 1 credit = 15 tokens | /features/extract |
| /agent | Dynamic — typically 100–500 per run | /features/agent |
The docs are refreshingly honest about why the surcharge exists. On the question format they write it out: “5 credits per page (1 base + 4 additional for the LLM call).” You are not paying for the page. You are paying for the inference.
What This Does to Your Cost Per 1,000 Pages
Run it against the $99 Standard plan, which includes 100,000 credits.
| Operation | Credits / 1,000 pages | Cost / 1,000 pages | Pages per $99 plan |
|---|---|---|---|
| Plain markdown scrape | 1,000 | $0.99 | 100,000 |
| Scrape + JSON extraction | 5,000 | $4.95 | 20,000 |
| Scrape + JSON + enhanced proxy | 5,000–9,000* | $4.95–$8.91 | 11,111–20,000 |
| 40-page PDF | 40,000 | $39.60 | 2,500 PDFs |
*Whether two +4 surcharges stack to 9 or absorb into 5 is not documented. I flag it rather than guess.
That second row is the whole article. A JSON extraction job burns your plan five times faster than a scraping job of identical size. A 100,000-page structured extraction is not a $99 month. It is a $499 month, because you need Growth.
Three Billing Behaviours That Run Backwards
Assembling the table surfaced three things that behave the opposite of how any reasonable person would assume. These are the ones that will actually cost you money.
1. Caching saves time, not credits
Firecrawl markets “10x faster scraping through intelligent caching,” and the default maxAge is two days, so you are almost certainly hitting cache without knowing it. The docs are unambiguous about what that does to your bill:
“Cached results still cost 1 credit per page. Caching improves speed, not credit usage.”
Every architecture instinct says a cache hit should be cheaper. It is not. It is free latency and full price.
2. Lockdown Mode charges 5x precisely when it works
from firecrawl import Firecrawl
firecrawl = Firecrawl(
# No API key needed to get started — add one for higher rate limits:
# api_key="fc-YOUR_API_KEY",
)
# Serve only previously cached results. No outbound request is made.
# Returns SCRAPE_LOCKDOWN_CACHE_MISS if the URL is not in the cache.
scrape_result = firecrawl.scrape(
'https://firecrawl.dev',
formats=['markdown'],
lockdown=True,
)
print(scrape_result.markdown)
import { Firecrawl } from 'firecrawl';
const firecrawl = new Firecrawl({
// No API key needed to get started — add one for higher rate limits:
// apiKey: "fc-YOUR_API_KEY",
});
// Serve only previously cached results. No outbound request is made.
// Returns SCRAPE_LOCKDOWN_CACHE_MISS if the URL is not in the cache.
const scrapeResult = await firecrawl.scrape(
'https://firecrawl.dev',
{
formats: ['markdown'],
lockdown: true,
}
);
console.log(scrapeResult.markdown);
# No API key needed to get started — add the Authorization header for higher rate limits:
curl -X POST https://api.firecrawl.dev/v2/scrape \
-H 'Content-Type: application/json' \
-d '{
"url": "https://firecrawl.dev",
"formats": ["markdown"],
"lockdown": true
}'
# Serve only previously cached results. No outbound request is made.
firecrawl https://firecrawl.dev --lockdown
Lockdown serves from Firecrawl’s index without touching the live web. A cache hit costs 5 credits. A cache miss costs 1 credit. You pay a five-fold premium for success and a discount for failure — the exact inverse of every other endpoint. There is a logic to it, since a hit is the product working, but it is not what anybody budgets for.
3. Auto proxy mode makes the same URL cost 1 or 5 credits depending on the day
From the proxies documentation:
“If the retry with enhanced is successful, 5 credits will be billed for the scrape. If the first attempt with basic is successful, only the regular cost will be billed.”
Your bill is now a function of whether the target’s anti-bot happened to fire. Same script, same URL, same schema — 400% cost variance, driven by something outside your control. If you need forecastable spend, pin the proxy mode.
There is a fourth, smaller one worth knowing: a page that loads is billable even if it is useless. Firecrawl does not charge for its own failures — timeouts, server errors. But a 404 page, or a Cloudflare block page, is a successful fetch and you pay for it.
The /agent Problem
If you have looked at /agent — the successor to /extract — the pricing is honest about being unpriced. Five free runs a day, then “dynamic pricing.”

What that means in practice, per the extractor guide: a representative agent task consumes roughly 100 to 500 credits. A single run. There is a maxCredits parameter and its default ceiling is 2,500.
Sit with that. One uncapped agent run can consume 2.5% of an entire $99 monthly plan. Twenty of them empty it.
The mitigation is documented and worth taking seriously. spark-1-mini is the default model and uses roughly 60% fewer credits than spark-1-pro on equivalent tasks.
Firecrawl’s own guidance is blunt: if you already know the URL, use /scrape with a JSON format at 5 predictable credits, and reserve /agent for when discovery is genuinely required. Their words, not mine — the extractor guide calls the JSON scrape “the cheapest, fastest, and most predictable option.”
Why You Cannot Audit This From the API
Here is the finding I did not expect, and it is the reason this article exists rather than a spreadsheet.
Firecrawl has no per-request cost attribution. None.
There are four usage endpoints — /team/credit-usage, /team/token-usage, and historical variants of both. The historical endpoints accept exactly one parameter, byApiKey. The finest granularity available anywhere in the API is billing period, optionally split by API key.
You cannot ask “what did request abc123 cost.” The only endpoint that returns a creditsUsed field at all is batch scrape and crawl status. A single /scrape response tells you nothing about what it just charged you.
So if you want per-page cost data, there is exactly one way to get it: difference the credit counter around an isolated request, on a key with no other traffic.
Here is the harness. It is short because the technique is simple; the discipline is in the isolation.
import os, time, requests
BASE = "https://api.firecrawl.dev/v2"
H = {"Authorization": f"Bearer {os.environ['FIRECRAWL_API_KEY']}",
"Content-Type": "application/json"}
def balance():
r = requests.get(f"{BASE}/team/credit-usage", headers=H, timeout=30)
r.raise_for_status()
return r.json()["data"]["remainingCredits"]
def measure(label, payload, settle=6):
before = balance()
t0 = time.time()
r = requests.post(f"{BASE}/scrape", headers=H, json=payload, timeout=180)
elapsed = time.time() - t0
time.sleep(settle) # let the counter settle
cost = before - balance()
print(f"{label:<34} {cost:>4} credits {elapsed:>5.1f}s HTTP {r.status_code}")
return cost
SCHEMA = {"type": "object", "properties": {
"name": {"type": "string"},
"price": {"type": "string"},
"features": {"type": "array", "items": {"type": "string"}}}}
URL = "https://example.com/your-test-page"
measure("markdown only", {"url": URL, "formats": ["markdown"]})
measure("json extraction", {"url": URL, "formats": [{"type": "json", "schema": SCHEMA}]})
measure("json + enhanced", {"url": URL, "formats": [{"type": "json", "schema": SCHEMA}],
"proxy": "enhanced"})
measure("summary", {"url": URL, "formats": ["summary"]})
measure("product", {"url": URL, "formats": ["product"]})
Three things matter for the result to mean anything. Use a dedicated API key with zero other traffic, or concurrent requests will poison the differential. Allow a settling delay — the docs do not state whether the counter updates synchronously, so assume it does not. And run each page type three times and take the mode, because a single auto-proxy retry will silently show you a 5 where the true baseline is a 1.
That last point is the whole reason this cannot be faked. You can copy a credit table from documentation. You cannot copy a run.
Where the Documentation Goes Silent
Being precise about the gaps matters as much as being precise about the numbers. Six things are genuinely undocumented as of July 2026:
- deterministicJson. Shipped in v2.11.0 on 24 June 2026, described in the changelog as generating a reusable cached extractor so “repeat scrapes are cheaper.” It does not appear in the scrape docs. It is not in the formats enum in the API reference. Its credit cost is published nowhere. A cheaper LLM-free structured extraction is exactly what a cost-conscious team wants, and there is no number attached to it.
- /parse billing. Neither the feature page nor the API reference contains a billing section. The response has no creditsUsed.
- Surcharge stacking. JSON plus enhanced proxy: 9 credits or 5? Unstated.
- summary, branding, changeTracking, product carry no documented surcharge and no statement of whether they invoke an LLM. Three of them almost certainly do.
- Which model backs the json format, and whether tokens count input, output or both. Never named.
- Batch scrape has no documented per-URL rate or volume discount.
One clarification while we are here, because it is widely misread. Firecrawl’s claim that the question and highlights formats are “up to 100x more token-efficient” is about your LLM bill, not your Firecrawl bill. Those formats save your model from reading a full page. On Firecrawl’s side they are a 5x increase. Both things are true and the launch post says so plainly.
The Final Word
None of this is Firecrawl being dishonest. Every number in the table above came from their own documentation, written clearly, in public. The failure is one of assembly. The pricing page shows six lines and the FAQ says “etc.,” and the other nine lines live on five different pages that nobody reads before signing up.
That gap has a practical cost. If you budgeted a structured extraction project at 1 credit per page, you are wrong by 400% before you write a line of code, and you will find out in week three when the balance hits zero.
So do three things. Price extraction at 5 credits, not 1. Pin your proxy mode instead of leaving it on auto, or accept that your forecast has a 400% variance band built in.
And if a project depends on this arithmetic, spend twenty minutes running the harness above against your own key, because Firecrawl cannot tell you what a single request cost and no article — including this one — can measure your pages for you.
Affiliate Disclosure: This post may contain some affiliate links, which means we may receive a commission if you purchase something that we recommend at no additional cost for you (none whatsoever!)
Similar Posts

About the author:
Aliakbar Fakhri
founder & CEO of AFFiNCO








