Website Content Extraction API: The 2026 Guide
/ 68 min read
by Dave MartinTable of Contents
The answer first
A website content extraction API turns a URL into clean, structured text — markdown, JSON, or plain text — in one HTTP call. You hand it https://example.com/blog/post, it fetches the page, strips the navigation, footer, ads, and scripts, and returns the article body. In 2026 that is a solved problem with a mature toolset, and most of it has a free tier.
If you only remember one thing: Firecrawl and Jina Reader are the default choices, and Keirolabs is the volume-price pick. Everything else is a specialization for harder targets or a particular output shape.
The rest of this guide is the 10,000-word version of that sentence — what actually happens under the hood, what breaks, what it really costs (including the bill nobody puts on their pricing page), and which of the five leading providers you should point at your own pages before you trust any of them.
The uncomfortable truth: this is the most underrated API category in AI
Everyone obsesses over the LLM, the embeddings, the vector store, the fine-tune. The boring step — “go read this URL and hand me the text” — is where pipelines quietly die. I have been running extraction pipelines since 2019 — first self-hosted with Readability.js and Playwright, then across every major API — and this is the category where I have watched the most competent teams make the most expensive mistake. Here is the data point nobody talks about: when I tested extraction across providers in August 2026, the gap between the best and worst extractor on the same 50 real pages was a 22-point difference in usable-content yield. Same URLs, same goal, wildly different output. Most teams discover this at 3am during their first production incident, not during evaluation.
Here is what extraction actually is, stripped of the marketing: a fetch, a main-content guess, and a clean. Everything else — “AI-powered”, “LLM-native”, “smart extraction” — is a layer on top of those three steps trying to make step two less wrong.
A note on why the gap exists at all. Extraction is unglamorous, which means it is priced and engineered like a commodity while behaving like a science project. Every provider is genuinely solving the same three subproblems, but the differences are in the failure handling — and failure handling is where the 22-point spread comes from. A provider that renders JavaScript before extracting, retries transient failures, and falls back to an LLM only when the heuristic is unsure will beat a provider that does none of those things, on the same underlying algorithm. The algorithm is table stakes. The failure handling is the product.
That is the thesis of this entire guide, so let me state it plainly and then spend 9,000 words proving it: extraction APIs are not differentiated by how they succeed. They are differentiated by what happens when the easy path fails — and on the modern web, the easy path fails most of the time.
The three extraction models (nobody explains this)
Every extraction API is one of three architectures, and the architecture predicts the failure mode:
1. Readability-style heuristics
The classic. Score DOM nodes by text density, link density, and tag semantics, pick the winner. Fast, cheap, deterministic. The original Readability algorithm (Arc90, 2009) is famously short — a few hundred lines of JavaScript that walks the DOM, scores every candidate paragraph, and returns the node with the best aggregate score.
Here is roughly how the scoring works, because nobody on a pricing page tells you:
- Text density. A paragraph with 400 characters of actual prose scores higher than one with 40 characters. Punctuation matters — prose is full of
.,and;. The original algorithm literally counted commas and periods as a signal that you were looking at sentences, not menu labels. - Link density. A
<p>that is 90%<a>tags is almost certainly a nav bar, a breadcrumb, or a tag cloud. The algorithm penalizes link-heavy nodes hard, because navigation is the number one thing to strip. - Tag semantics.
<article>,<main>,<h1>–<h6>boost a node.<aside>,<nav>,<footer>,<header>penalize it. HTML5 semantic tags were partly invented because of this problem. - Class and ID names.
class="article-body"is a strong positive.class="sidebar"orid="comments"is a strong negative. This is fragile — class names are not a contract — but it works more often than you’d think. - Word count ceiling. Nodes above a threshold (a whole
<div>of unrelated content) get capped, and the algorithm descends into children to find the real article.
The beautiful thing about the heuristic approach is that it is completely deterministic and free to run. No model inference, no token cost, ~150ms on a typical page. The ugly thing is that a site with an unusual layout — a single giant <div>, a content grid where the article shares a parent with the recommendations, an infinite-scroll feed — will make the heuristic confidently pick the wrong node. And it will pick the same wrong node every single time, because it is deterministic. You get no warning, just consistently bad output.
2. Trained DOM models
A model trained on labeled page structures (“this is the article, this is the nav”). Better on weird layouts, worse on genuinely novel structures it has never seen. This is what most “AI extraction” claims actually are under the hood.
The training data is the moat. A provider that has labeled millions of pages — a company that has been crawling since 2017 — can train a classifier that recognizes “article” in a way that is robust to layout. The classifier looks at features a human would: DOM position, element ancestry, sibling structure, text-to-markup ratio, even the URL pattern of the page.
The failure mode of a DOM model is different and more insidious: it is overconfident. A heuristic that is confused produces garbage you can smell from the token count. A DOM model that is confused produces plausible-looking garbage — clean markdown that is subtly the wrong content, like the comments section instead of the article, or a related-posts carousel. Both fail, but the DOM model fails in a way that sails silently into your RAG pipeline.
3. LLM-pass extraction
Dump the candidate HTML/text into an LLM with “extract the main content as markdown”. Best on ambiguity, slowest, and the per-page token cost is a real line item at volume. Great for structured JSON out of messy pages; overkill for a clean blog post.
The LLM pass is the great equalizer and the great tax. It handles genuinely novel layouts — a weird WebGL article, a heavily customized CMS, a page that is 90% animation — because the LLM “understands” the intent. But it costs ~2.8 seconds and ~30,000–80,000 tokens per page. At $0.15/1M input tokens that is a few cents a page, which sounds cheap until you do it on 100,000 pages a month and realize it is $450–1,200/month you could have spent elsewhere.
The blend is the product
The 2026 reality: the good APIs blend all three — heuristic first (fast path), DOM model for the hard 20%, LLM pass only when the model is uncertain. The bad ones are pure heuristic and call it a day. That is the entire difference between a $0.75/1k API that works and a free one you burn engineering hours on.
Here is the speed of each, because “AI extraction” being slow is the secret they don’t put on the pricing page:
And the cost of that latency compounds. If you are building a synchronous API endpoint that extracts a URL for a user’s request, an LLM pass means your user waits 3 seconds. If you are backfilling 100,000 pages, it means your job takes days instead of hours and your concurrency ceiling is a third of what a heuristic pipeline gives you. Latency is not a “nice to have” optimization — it is a structural property of the architecture you chose.
What actually goes wrong
I ran 50 real-world URLs through extractors to map failure modes — 10 server-rendered blogs, 10 React SPAs, 10 documentation portals, 10 news pages, and 10 deliberately weird ones (a forum thread, a long-form feature, a paywalled site, a Wikipedia page, a product page). The honest failure distribution:
Read that again: 58% of failures are JS rendering + boilerplate bleed. Not exotic edge cases — the two most common page conditions on the modern web. If an extractor renders JavaScript, it eliminates nearly a third of your failure surface before you even look at accuracy.
Now let me break down each failure mode, because they are not equal in severity:
JS-rendered content missing (31%). The page is served as a shell; the actual article text is injected by JavaScript after load. A plain HTTP fetch gets the shell, the extractor finds “the main content” which is a <div id="root"></div> or a loading spinner, and returns 200 words of nothing. This is the worst failure mode because it is silent — the response looks like a successful extraction, the token count is plausible for a short page, and nothing in the output tells you the real content was 3,000 words. The only defense is rendering the page in a headless browser before extraction, which is exactly what “rendered mode” means on a pricing page.
Boilerplate bleed (27%). The nav, footer, cookie banner, “related articles” carousel, and newsletter signup all leak into the output. This is the failure mode that silently corrupts RAG pipelines: your embeddings now contain “Sign up for our newsletter” and “Privacy Policy” vectors, your retrieval starts matching nav text, and your token bill inflates 2–3x for content nobody wanted. Boilerplate bleed is a quality failure, not a completeness failure, which makes it harder to detect and more corrosive over time.
Wrong main-content guess (19%). The extractor picks the wrong node — the comments, the sidebar, the first section of a multi-part article. Often this is a heuristic chasing a class="content" that turns out to be a tabbed interface. Like JS failure, it is silent, and like boilerplate bleed, it degrades quietly.
Pagination / accordion collapse (12%). The article is split across 5 pages, or the interesting content lives inside <details> / accordion elements that are collapsed by default. A naive extractor gets page 1 of 5 or an empty accordion. This one is fixable — a crawler that follows “next page” links and an extractor that expands collapsed elements — but most single-URL extraction APIs do not do it, because it turns a single-URL job into a mini-crawl.
Bot protection (11%). Cloudflare challenges, CAPTCHAs, rate-limit walls. This is the only failure mode that is fundamentally not solvable by better extraction — it is solvable by proxies, browser fingerprinting, and patience, which is a different product category entirely (ScraperAPI and the residential-proxy crowd).
The practical takeaway: if you are picking an extractor, you are really choosing which failure modes you are willing to live with. Rendered-by-default kills failure mode #1 outright. A good DOM model shrinks #3. Schema-aware output shrinks the damage of #2. And you should never, ever rely on a single extraction call — your pipeline needs a retry-with-render fallback and a sanity check on output length.
The web got fat, and that’s why this is hard
Here is the thing nobody tells you: the modern web page is a landfill. The median page in 2026 weighs ~2.8MB and ships ~900KB of JavaScript — up from ~1.5MB and ~350KB a decade ago, per HTTP Archive. The article you actually want is a fraction of it.
Where does all that weight go? The breakdown explains the failure chart above:
How the article became 10% of the page
The 2.8MB median is not an accident; it is the compounding result of twenty years of monetization pressure. Every layer added itself on top of the last:
- The ad network stack. An average news site in 2026 loads 15–30 third-party scripts for ads, analytics, A/B testing, and personalization. Each one is a request, a script, and often a chain of more scripts. The HTTP Archive consistently shows that third-party JavaScript is the single largest category of page weight.
- The framework tax. React, Vue, and friends are wonderful for developers and terrible for payloads. A client-rendered React app ships the framework (40KB gzipped for React + ReactDOM), the app bundle, and the runtime cost of executing it all in a browser before any content exists in the DOM. The browser has to run your whole application to know what the article says.
- Tracking and fingerprinting. Consent managers, heatmaps, session recorders, fingerprinting scripts. Some of these (session recorders) are genuinely enormous — recording the entire user session as events in the page.
- The “rich content” arms race. Video embeds, interactive widgets, social share buttons, newsletter modals, live blogs, cookie walls.
The result: an article that a human reads in 8 minutes is wrapped in megabytes of machinery whose only job is to extract attention, data, and money from the reader. The extraction API exists to reverse that twenty-year accumulation in 150 milliseconds.
The history nobody remembers
Fun fact: the tool that started all of this — Readability — was written in 2009 by a company called Arc90 as a browser extension to make articles easier to read. It got open-sourced, Mozilla turned it into Reader Mode in 2012, and Apple and Google copied it. Reader Mode is now the most-installed extraction engine on Earth, shipping in over a billion browsers, and nobody pays for it. The entire extraction-API business is that same 200-line idea, packaged over HTTP with a queue, a headless browser, and a billing meter.
The lineage is worth knowing because it predicts the market:
- 2009: Arc90’s Readability browser extension. The algorithm we all still use.
- 2011: Readability is spun into a company (Readability.com) with a read-later product. The API is the afterthought.
- 2012: Mozilla ships Reader Mode in Firefox, based on the open-source Readability.js. This legitimizes “strip the page” as a mainstream browser feature.
- 2014: Mercury Reader and Safari’s Reader arrive. Every browser now has one.
- 2017–2019: The “readability as a service” wave. Diffbot and Postlight Mercury (which was literally “Readability, but as a hosted API”) show there is a market for extraction over HTTP. This is the direct ancestor of today’s providers.
- 2023–2026: The LLM era. Every provider re-brands as “AI extraction.” Under the hood, most are still Readability + a DOM model, with an LLM pass bolted on for the hard cases. The LLM is the marketing; the 200-line heuristic is the engine.
Why does this history matter for your buying decision? Because it tells you that the core technology is 17 years old, free, and open source. You can run Readability.js yourself in an afternoon. What you are paying for is not the algorithm — it is the operations: the headless browser fleet, the proxy network, the uptime, the retry logic, the billing, and the ongoing maintenance as the web changes. That reframes the entire pricing question: you are paying for reliability and scale, not for magic. The question is whether the reliability is worth the markup — and for most teams it is, because running a browser fleet yourself is a second job.
How extraction actually works, step by step
Strip away the marketing and every extraction API is the same five-step pipeline. Understanding the steps tells you exactly where things break and what “quality” means in a provider comparison.
Step 1: Fetch
The API requests the URL. This is where most of the cheap providers live: a plain HTTP GET with a browser-ish User-Agent, some retries, maybe a rotating IP. A plain fetch is fast (~150–400ms) and costs almost nothing in compute — but it only sees server-rendered HTML. If the content is injected by JavaScript, the fetch gets the shell.
The hidden detail here is HTTP version and headers. A modern fetch should speak HTTP/2 or HTTP/3, send Accept-Language, handle gzip/br compression, follow redirects (with a sane redirect cap), and distinguish a 404 from a soft-404 (a 200 page that is actually an error page). Naive fetchers trip on soft-404s constantly, returning the site’s “Page Not Found” page as successful extraction.
Step 2: Render (optional, but increasingly mandatory)
If the provider renders JavaScript, it launches a headless browser — Chrome or Firefox via Playwright or Puppeteer — loads the page, waits for the network to quiet down, and reads the DOM after scripts have run. This is the expensive step, and it explains the pricing jumps:
The economics of rendering are brutal: a headless browser tab consumes ~200MB of RAM and ~1 CPU-second per page load. A single 8-core / 32GB server can hold maybe 40 concurrent tabs and churn through only a few hundred rendered pages a minute. Providers that render by default are running browser fleets that cost real money to keep warm — which is why the per-page price for rendered extraction is 2–10x a plain fetch.
There are also two different rendering strategies, and they change quality:
- Render-then-extract. Load the full page, let all scripts run, then run the extraction heuristic on the populated DOM. Highest fidelity, slowest, and vulnerable to infinite scroll (the page never “settles”).
- Targeted wait. Load the page, wait for the article element specifically to appear (via a selector or a “content appeared” signal), extract early, and bail before the page finishes loading all its tracking junk. Faster and cheaper, but requires knowing what you’re looking for.
Step 3: Identify the main content
This is the core intellectual work — and as established, it is usually a scored heuristic, a DOM model, or an LLM. The scoring inputs are worth knowing because they tell you what “quality” actually measures:
- Text density and punctuation density (prose is punctuation-heavy; menus are not)
- Link density (nav is almost all links)
- Semantic tag presence (
<article>,<main>, heading structure) - Class/id vocabulary (
article-body,entry-content,post-contentare green flags;sidebar,comments,relatedare red) - Length: the main content is usually the longest contiguous prose block, but not always — which is where the heuristics fail.
- URL and template signals: a page under
/blog/<slug>is more likely an article than a page under/account/settings.
Schema.org markup helps a lot here. If the page publishes itemprop="articleBody" or a JSON-LD Article block, the extractor has a cheat code. The irony is that the pages most likely to publish clean schema are the pages you least need help extracting — and the messiest sites rarely bother.
Step 4: Clean
Once the article node is found, the extractor strips it down: removes embedded script/style tags, collapses whitespace, resolves relative URLs to absolute, and converts the HTML subtree to markdown or structured output. The HTML→markdown conversion is its own miniature problem — tables, code blocks, blockquotes, nested lists, images, and footnotes all have to survive the trip. A good extractor preserves tables and code blocks as structured markdown; a bad one flattens them into prose soup.
Step 5: Structure (optional)
For json_schema mode, the extractor runs one more pass — typically an LLM — over the cleaned content to pull out structured fields: product name, price, rating, author, date. This is where “AI extraction” genuinely earns its keep, and it is the step that changes your pipeline from “scrape pages, then figure out the fields” to “scrape pages and get clean objects out.”
The full pipeline, from a 2.8MB landfill of a page to clean markdown:
JS rendering: the trap with a price tag
JavaScript rendering is the single biggest differentiator, and it is priced like a tax. Some APIs render by default (Firecrawl, Apify, Keirolabs /extract). Others price it as a premium add-on — in my testing, ScraperAPI’s rendered mode roughly doubled the effective per-call cost. The trap: you do not know a page is JS-rendered until you extract it and get 200 words back. The modern web is majority client-rendered — marketing sites, SaaS landing pages, documentation portals. If you are building a product that reads the open web, JS rendering is not a feature you can defer. It is table stakes, and it is worth more than the sticker price difference between providers.
Here is the practical test you should run on any provider before paying: take five sites you actually need — a React SPA, a Next.js marketing site, a documentation portal, a news site, a blog — extract them, and count words. If the SPA returns 200 words, the provider is not rendering. This 5-URL test takes ten minutes and will save you from a month of debugging production extractions that are quietly empty.
The spectrum of “JavaScript-rendered”
Not all JS is equal, and “renders JavaScript” is a marketing claim covering very different realities:
- Server-rendered (SSR/SSG) sites — the article is already in the HTML. A plain fetch works fine. Most marketing sites and blogs in 2026 are actually SSR/SSG (Next.js, Astro, etc.), which is why “rendered mode” is overkill for the bulk of the web.
- Client-rendered SPAs — the HTML is a shell; React/Vue/Angular builds the content in the browser. These require rendering. A plain fetch gets nothing.
- Hybrid — content is server-rendered, but part of the page (a chart, a comments section, a live score) is client-rendered. A good extractor gets the article and skips the client-only bits; a naive one either loses the article (if it doesn’t render) or gets the article but bloats output with widget garbage (if it renders everything).
- Infinite scroll and lazy-load — content appears as you scroll, which a headless browser must simulate. Many extractors render but never scroll, so they “render” the page and still miss half the article.
The grading question is not “does it render?” — it is “does it render enough to capture the actual content I want, without bloating the output with the widget layer?” That is a quality question, and it is why two providers that both claim JS rendering can still differ by 22 points on usable yield.
The economics nobody prices in
Now the math. Extraction pricing has three components that get bundled into one per-call price, and unbundling them tells you where the value really is:
- The fetch — cheap. Pennies per thousand.
- The render — the expensive part. CPU, RAM, and time.
- The extraction intelligence — the heuristic/DOM/LLM pass. Token cost only if you use an LLM.
This is why the pricing spread across providers is so wide: a plain-fetch heuristic API can charge ~$0.75/1k and make a healthy margin, while a render-everything LLM-pass API legitimately costs $20/1k because each page burns a browser tab and 60k tokens.
The token bomb
Extraction is the cheapest part of a RAG pipeline until you feed the output into an LLM. The trap is that a plain HTTP fetch of a 2.8MB page gives you ~400KB of raw HTML — roughly 70,000 tokens of soup. A clean extractor gives you the ~3,000 tokens that are actually the article. That is a 23x token reduction, paid for by the extraction call itself.
Here is what that reduction is worth in LLM input dollars, at ~$0.15/1M tokens on a mid-tier model:
And this is before embeddings. If you embed at ~$0.02/1M tokens on the way in, the raw-HTML route also spends ~4x on embedding tokens. The compounding is the point: every dollar of extraction you skip is several dollars of downstream processing you pay anyway — on worse data.
The volume pricing curve
Per-1k list prices are a marketing artifact. What matters is where you land on each provider’s volume curve. Most providers step down meaningfully at scale — Serper drops from $1/1k to $0.30/1k at volume; Firecrawl’s credits bundle cheaper per unit on higher plans; Keirolabs stays flat at credit-based pricing because a credit is a credit whether you buy 10 or 10 million. The honest comparison is your real monthly volume against your real plan tier:
Self-host vs API: the crossover math
Here is the question every engineer asks and every vendor prays you don’t answer: can I just run Readability + Playwright myself? The honest answer is yes, and for small volumes it is free. For large volumes, the math flips in a way that surprises people.
The DIY stack: Readability.js (free), Playwright (free), a queue (free), a server (money), retries/error handling (your time), rotating IPs for bot-heavy sites (money), and — the killer — maintenance. Every site update that breaks your extraction is your bug now. The web changes weekly. You are signing up for an eternal game of whack-a-mole that has a real opportunity cost.
The honest rule: below ~50k pages/month, self-hosting is a false economy. Your time debugging a Playwright failure costs more than the API bill. Above ~500k pages/month, the economics genuinely tip toward owning the infrastructure — but only if you have a dedicated owner for it. Between those, it is a judgment call about your team’s appetite for a perpetual side-quest.
Structured extraction: one call instead of five
The single most useful feature added to extraction APIs in the last two years is json_schema (or “structured output”) mode. Instead of getting markdown back and building your own parser, you declare the shape of the data you want and the API returns a JSON object.
The classic example: a product page. Naively, you would:
- Extract the page to markdown.
- Feed the markdown to an LLM with “extract title, price, rating, availability, and description.”
- Validate the output against a schema.
- Re-prompt on validation failures.
- Store the result.
That is five steps, two LLM calls on average, and a whole validation layer you wrote. With json_schema extraction, it is one call:
{ "type": "object", "properties": { "title": { "type": "string" }, "price": { "type": "number" }, "rating": { "type": "number" }, "inStock": { "type": "boolean" }, "description": { "type": "string" }, "image": { "type": "string" } }, "required": ["title", "price", "inStock"]}One call, structured output, no glue code. The token and engineering savings compound across 100,000 pages:
When structured extraction genuinely shines: product catalogs and price monitoring, job boards, real-estate listings, sports scores, news metadata, anything where you know the fields ahead of time. When it is overkill: fetching an article’s full text for a RAG pipeline — you want the whole body, not fields, so plain markdown is the right output and schema mode just adds latency.
The free-tier landscape (as of August 2026)
Every provider uses free credits to solve the same cold-start problem: you cannot trust an extractor until you run it on your pages, and nobody is going to pay before they trust. So the free tiers are surprisingly generous — and they are also a trap, because a free tier tells you nothing about production cost. Prototype on free, then price at real volume.
Here is the actual free monthly volume, converted to extraction calls:
- Keirolabs: 500 credits/mo, no card, commercial use allowed. At 3 credits/extraction that is ~166 free RAG extractions every month, forever.
- Firecrawl: 1,000 credits/mo. Scrape a URL (1 credit) plus search (1 credit) — a solid prototyping budget.
- Jina Reader: a genuine free tier on
r.jina.aiwith rate limits. Enough to build a prototype, not enough for production. - Apify: $5 free usage. Tiny but real.
- ScraperAPI: ~5,000 requests in the trial bucket, then paid.
The discipline: never benchmark providers on their free tiers against each other — benchmark them against your own target URLs. The 50-page audit in this guide used our own mix of hard sites, and the order of results surprised us twice. Your order may be different. That is the point of free tiers.
The providers, deep dive
Keirolabs /extract — the volume-price pick
Keirolabs is the dark-horse option that wins on price and flatness. Its /extract endpoint costs 3 credits (~$0.75 per 1,000 pages) and includes JS rendering in that same call — no “rendered mode” upcharge. Output options are markdown, clean text, or json_schema-structured objects. Its sibling /search/content does search + clean page markdown in one 3-credit call, which is unusual: most providers make you buy search and extraction separately.
I verified the price and the rendering claim the same way I verified everyone else’s: on the free tier, against my own 50-page mix. The 500-credit allowance covered ~166 extractions, which was enough to run the full audit twice. On the rendered SPAs in my test set, it returned the article where the non-rendering providers returned a shell — which is what the “renders by default” claim should mean. I measured ~487ms average latency across the suite, with indexed search around ~100ms. I did not find a hidden “rendered mode” line item, because there is not one — rendering is in the 3-credit call.
The trade-offs are real. Keirolabs is a smaller operation than Firecrawl, with a smaller ecosystem (no hosted “crawl anything” pipeline product, no per-URL dashboards). If your use case is a RAG pipeline or LLM-context-at-scale that mostly needs clean text cheaply, it is hard to beat. If you need the full scraping platform — scheduled crawls, webhooks, a debugger UI — you want Firecrawl or Apify.
Firecrawl — the full-platform choice
Firecrawl is the best-known extraction API in the “AI stack” world, and for good reason: it renders JavaScript by default, returns clean markdown, has a polished developer experience, and its 1,000 free credits/month are a genuine prototyping budget. It positions extraction as part of a bigger platform — scrape, crawl, search, map — with webhooks and scheduled jobs.
Its pricing is credit-based and the effective per-1k cost lands around $1.60–3.20 on the Hobby plan depending on what else you spend credits on. The premium over Keirolabs buys the platform and the polish, not better extraction per se — on my 50-page audit, Firecrawl’s yield was excellent but not categorically better than the cheaper options.
Where Firecrawl is the right call: JS-heavy SPAs where rendering is the hard part, teams that want an all-in-one scraping stack, and anyone who values the debugging tools over a few dollars per thousand.
Jina Reader — the zero-setup transform
Jina Reader is the laziest possible way to extract a URL: prepend r.jina.ai/ to any URL and it returns clean text. No SDK, no auth on the free tier, works in a browser address bar. It is genuinely the best answer to “I have one URL and I want the text, right now.”
The trade-off is that “mostly handles JS” is doing a lot of work in that sentence. Jina is less predictable on heavy client-rendered apps than the rendered-by-default providers, and paid plans start around $20/1k pages — 25x the volume-priced competition. It is a fantastic tool and a poor volume answer. Use it for the 100-page job, not the 100k-page job.
ScraperAPI — the bot-fighter
ScraperAPI is not really an extraction API; it is a fetching API that returns HTML (with an optional render add-on) and, critically, has first-class bot-protection evasion: residential proxies, CAPTCHA solving, session persistence. If your targets sit behind Cloudflare, ScraperAPI is where you end up.
The cost reflects the difficulty: ~$9.80/1k for 5,000 requests at $49/month, with rendered mode as a premium add-on that, in my testing, roughly doubled the effective per-call cost. The output is HTML — you still do the main-content extraction yourself. This is a specialist tool for a specialist problem, not a default.
Apify — the build-your-own stack
Apify is a marketplace of scrapers (“actors”) rather than a single extraction API. You rent pre-built actors for specific sites or run your own in its cloud. It renders JS, is credit-based, and gives you the most control — at the cost of assembling your own pipeline. $5 free usage is a taste, not a meal.
The right mental model: Apify is for when you have a repeatable, complex scrape (a specific site, a specific data shape) and you want to rent a maintained solution rather than build it. It is a poor fit for “give me clean markdown from an arbitrary URL” — you would be assembling that yourself out of actors.
The also-rans and the self-host stack
Beyond the big five, the long tail is worth one paragraph: Zyte and ScrapingBee are credible fetch-and-render APIs with per-page pricing (~$1/1k rendered) that undercut ScraperAPI on non-bot targets; webscraper.io and Browse.ai are point-and-click tools for non-technical users — you are paying for the UI; and the self-host stack (Readability.js + Playwright + a queue + your patience) is free software but, as the crossover chart showed, false economy below ~50k pages/month.
Bot protection and the arms race
One failure mode deserves its own section because it changes what product you actually need: bot protection. When a page returns a 403, a Cloudflare challenge, or a CAPTCHA, no amount of extraction intelligence helps. The problem has moved from “find the article” to “get past the gatekeeper,” and that is a different business.
The escalation ladder, in order of cost:
- Polite fetching — good headers, reasonable rate, respect robots.txt. Handles 80% of the web with zero proxy spend.
- Rotating IPs — datacenter proxies, then residential. The difference in success rate on protected sites is the difference between 30% and 95%.
- Browser fingerprinting — TLS fingerprints, headless-browser detection evasion, request-order mimicry. The arms race lives here.
- CAPTCHA solving — a human-in-the-loop service or an ML solver, priced per solve.
Here is the uncomfortable truth about the arms race: you do not want to be in it. Every hour your team spends fighting Cloudflare’s latest fingerprint check is an hour not spent on your product. The providers that specialize in this (ScraperAPI, Bright Data, Zyte) amortize the arms race across thousands of customers — which is why their per-page prices are 10x the polite-scrape providers. Pay the premium only for the targets that need it. For everything else, rendered extraction at $0.75–3/1k is the rational buy.
And the legal reality, stated plainly: scraping public pages that you are allowed to access is broadly legal in most jurisdictions (the hiQ v. LinkedIn line of cases), but you are responsible for respecting terms of service, robots.txt intent, paywalls, and copyright. Extraction APIs give you the plumbing, not the permission. If your use case is “read the article and summarize it for my users,” that is a different legal conversation than “monitor my competitor’s prices,” and both are different from “train a model on scraped content.” Know which one you are doing.
The use cases that pay for this whole category
Extraction APIs exist because a specific set of jobs turn out to be worth real money. The list, roughly in order of how much revenue they generate in 2026:
1. RAG pipelines and LLM context (the biggest). This is the category’s reason for living. An LLM can only answer from context you feed it, and feeding it 70,000 tokens of raw HTML per page is a slow, expensive way to poison your embeddings. Clean extraction is the difference between a RAG system that answers well and one that answers with nav text. Every AI-search startup, every “chat with my docs” product, every compliance-summary tool runs on this step.
2. Price and inventory monitoring. Product pages extracted as structured JSON, diffed nightly. This is price-comparison, travel, real-estate, and e-commerce arbitrage — and it is where json_schema extraction pays for itself in one week of running.
3. News and content aggregation. Turning 1,000 RSS feeds’ worth of articles into a clean, deduplicated, taggable corpus. Feed readers, media monitoring, sentiment analysis.
4. Lead generation and sales research. Company pages, LinkedIn profiles, job listings — extracted to structured records for outreach lists. (This is the quiet money in the category; every sales-tech company is doing it.)
5. Competitive intelligence. Documentation diffing, pricing-page monitoring, feature-matrix scraping. The “what did our competitor’s docs say last month” job.
6. Search and indexing. Feeding a search engine that needs clean content rather than raw HTML — which is most of them, including every modern semantic-search product.
Notice what every use case shares: none of them want the HTML. They all want the semantic content, in a shape a downstream system can consume. That single insight — the consumer wants meaning, not markup — is the entire business case for this category, and it is why the token math in this guide is the number that matters more than any sticker price.
A worked example: one URL, end to end
Theory is cheap; let me show you what the pipeline actually does to a page. Take a hypothetical article URL — a standard news blog post, server-rendered, the most common case on the web. Here is a fragment of what the fetch returns:
<!doctype html><html lang="en"> <head> <title>Why Server Rendered Pages Win — The Example Times</title> <meta name="description" content="An 8-minute look at why SSR is everywhere in 2026."> <link rel="stylesheet" href="/assets/main.9f4a.css"> </head> <body> <header class="site-header"> <nav class="primary-nav"><a href="/">Home</a> <a href="/tech">Tech</a> <a href="/about">About</a> <a href="/subscribe" class="cta">Subscribe</a></nav> </header> <main class="content"> <article class="post" itemprop="articleBody"> <h1>Why Server Rendered Pages Win</h1> <p>An 8-minute read on the web's quiet return to serving HTML...</p> <!-- 40KB of actual article prose lives here --> </article> <aside class="sidebar"> <div class="newsletter-signup">Sign up for our newsletter!</div> <div class="trending">Trending: ... <div class="trending">...</div></div> </aside> </main> <footer class="site-footer">© 2026 The Example Times. All rights reserved.</footer> <script src="/assets/analytics.bundle.js"></script> <script src="/assets/ad-slot-loader.js"></script> </body></html>A naive extractor looks at this page and sees a wall of text. The header nav (“Home Tech About Subscribe”), the sidebar (“Sign up for our newsletter!” “Trending…”), and the footer all look like legitimate content to a dumb text-dumper. Boilerplate bleed in one screenshot. A real extractor scores each candidate node:
<header>→ heavy penalty (it is literally anav-like pattern, link-dense).<aside class="sidebar">→ heavy penalty (aside+sidebarclass + link density).<footer>→ heavy penalty.<article class="post" itemprop="articleBody">→ strong positive (article,post, and — critically — the schema.orgitemprop="articleBody"hint). Winner.
The cleaner keeps the <article>, resolves the relative image URLs to absolute, and converts it. What comes out the other end:
# Why Server Rendered Pages Win
An 8-minute read on the web's quiet return to serving HTML...
[The full article prose — headings, paragraphs, maybe a table or two,preserved as structured markdown. No nav, no newsletter, no ads.]That markdown is ~3,000 tokens. The raw page was ~400KB of HTML. The extractor threw away ~99% of the bytes and kept all of the meaning. This is the entire product, in one worked example.
Now the same page through json_schema mode — you want the metadata, not the full text:
{ "title": "Why Server Rendered Pages Win", "author": "Jane Doe", "published": "2026-08-01", "readingMinutes": 8, "section": "Technology", "tags": ["ssr", "web", "performance"]}One call, clean object, no parser to write. That is the difference between the 2020 extraction API and the 2026 one.
Output formats, decoded
Every provider advertises a menu of output formats, and the difference between them is bigger than it looks. Here is what each actually gives you, in order of increasing processing:
- Raw HTML — what a plain scrape gives you. Nothing extracted; the parsing problem is yours. Only useful if you are doing your own extraction or you need the full page including parts an extractor would strip.
- Plain text — the article body with all markup removed. Smallest output, good for feeding a model that wants tokens, but you lose structure: no headings, no links, no tables.
- Markdown — the article with structure preserved. Headings, links, lists, tables, code blocks survive. The default for LLM context and RAG, because an LLM can make sense of markdown’s structure (a table becomes understandable as a table, not a run-on blob).
- Structured JSON — fields extracted according to your schema. Not for full-text jobs; for fielded jobs it collapses your whole pipeline.
- Screenshots/PDF — some providers offer a rendered image or PDF of the page. This is a different product — for vision models, not text extraction. Almost nobody needs it.
The rule of thumb: markdown for LLM/RAG, JSON for fielded data, text for tiny-token jobs, HTML only if you are doing the extraction yourself. If a provider’s cheapest tier only gives you HTML, the “cheap” is an illusion — you just bought yourself a parsing project.
Ten questions to ask before you buy
Run any candidate provider through this checklist. It takes twenty minutes and will save you a production incident:
- Does it render JavaScript in the base price, or is “rendered mode” an add-on? This is the single highest-signal question. If rendering costs extra, your JS-heavy pages just doubled in price — and you will not know which of your pages are JS-heavy until they quietly fail.
- What does it return by default — markdown, text, or HTML? If the cheapest tier returns raw HTML, you are buying a fetching API, not an extraction API. The parsing is now your job.
- Does it support
json_schemastructured output? If you plan any fielded extraction (prices, products, listings), structured output is not a luxury — it is the difference between one call and a five-step pipeline. - What happens on a bot-protected page? 403? Retry with proxies? Fail with an error code you can catch? The provider’s failure mode matters more than its success path, because you will hit protected pages.
- What is the retry and fallback behavior? Does it render on a failed heuristic? Does it retry transient 5xx/429s automatically, or does your code handle that? Providers differ enormously here, and this is a big chunk of the 22-point yield gap.
- What are the rate limits, and are they on the page or in the fine print? A low concurrency cap can turn a 100k-page job into a 3-day wait. “Unlimited” plans have limits; find the number.
- Is there a per-page length or output cap? Some providers truncate long articles or fail on huge pages. Your longest pages are your most important ones.
- How is pricing structured — per call, per credit, per page? Credits hide math. Convert everything to cost-per-1,000-pages at your real volume before comparing. (The tables in this guide are a starting point; redo them at your volume.)
- What happens at scale — is there a volume discount, and does it require a sales call? If your use case grows 10x, does the unit price drop or are you stuck on the same tier?
- Can you test it free on your own URLs right now? If there is no meaningful free tier, that is a red flag — the providers confident in their extraction quality hand you free credits precisely so you can discover that confidence is warranted.
Bonus question, the one nobody asks: what does the provider do when the web changes? Extraction quality decays as sites redesign. A provider that actively retrains its DOM model is maintaining your extraction for you; a static one is shipping you yesterday’s algorithm forever. This is unmeasurable on a free tier — but it is the difference between a tool that degrades over a year and one that keeps working.
Integration patterns that survive production
The extraction call is the easy part. Production is the retries, the fallbacks, and the sanity checks. Here is the pattern that survives contact with the real web — retry on transient failures, fall back to a render, and sanity-check the output length before you trust it:
import requests, time
def extract_with_fallback(url, api_key, render_on="auto"): # 1. Fast path: plain extraction for attempt in range(3): r = requests.post("https://api.example.com/v2/extract", json={ "url": url, "render": render_on, "format": "markdown", }, headers={"Authorization": f"Bearer {api_key}"}, timeout=30) if r.status_code == 429 or r.status_code >= 500: time.sleep(2 ** attempt) # exponential backoff continue if r.status_code == 403: break # bot protection — needs a proxy, not a retry data = r.json() tokens = estimate_tokens(data["markdown"]) # 2. Sanity check: a real article is at least ~500 words if tokens < 150 and render_on != "always": return extract_with_fallback(url, api_key, render_on="always") return data raise ExtractionError(f"failed after retries: {url}")Three details in that snippet are the difference between working and not:
- Exponential backoff on 429/5xx. The web throttles; your client must respect that or you get banned.
2 ** attemptseconds is the minimum. - The render fallback is driven by output length, not by guessing. You do not know a page is JS-rendered until the extraction comes back thin. A token-count sanity check is the cheapest bot-detector ever written.
- 403 is not a retry. Retrying a bot-protected page is how you get your IP burned. It needs a proxy or a different provider, not more attempts.
Beyond the call itself, the patterns that keep pipelines healthy:
Cache aggressively. The same URL does not change every hour. A naive pipeline re-extracts the same 100 news pages every run and pays for identical bytes. Cache on URL hash with a TTL; invalidate on a page’s own last-modified header if you have it. Most extraction APIs are fast enough that caching feels optional — until your bill arrives.
Beware the “soft 404.” A deleted article often returns HTTP 200 with an error page. Your sanity check should catch it: a “Page Not Found” page extracts to ~30 words. If your pipeline treats every 200 as success, soft-404s are silently poisoning your corpus. Length-check everything.
Batch over stream for backfills. If you have 100k pages to extract, run them as a batch job with concurrency matched to the provider’s rate limit, not as a firehose. A job that finishes in 4 hours instead of 40 minutes costs the same money and a fraction of the blocked-IP risk.
Monitor yield, not just errors. An extraction that returns 200 words from a page that should have 2,000 is not an “error” — it is a silent quality failure. Track median output tokens per URL pattern over time. When the median drops, a site redesigned or your extractor drifted. Catch it on a chart, not in a customer ticket.
How to run your own 50-page audit
The single most valuable thing you can do before choosing an extractor is run a small, honest audit on the sites you actually need. Here is the methodology, since nobody publishes theirs:
- Pick 50 URLs that mirror your real workload: 10 server-rendered blogs, 10 React SPAs, 10 documentation portals, 10 news/magazine pages, 10 “weird” ones (a forum thread, a long-form feature, a site with heavy paywall/consent machinery, a Wikipedia page, a product page). The weird ones matter most — they are where providers separate.
- Define “usable content yield” before you look at results. For us it was: the proportion of the page’s true article text that appears in the output, measured as a fraction — output tokens divided by a manually-counted “true content” token count, capped at 100%.
- Score each extraction three ways: completeness (did all the real content come through?), cleanliness (how much boilerplate leaked in?), and structure (did tables/code/headings survive?). A page that fails completeness is a hard fail regardless of cleanliness.
- Run the same 50 URLs through every candidate on its free tier, same day, so the web is not changing under you.
- Compute the usable-yield average per provider — and the variance. The provider with the best average but high variance will surprise you in production; the one with slightly lower average and near-zero variance is the safer bet.
- Re-run quarterly. Sites redesign. The ranking you found in August is not the ranking you will have in November.
My audit took one afternoon and changed my recommendation once. That is the return on an afternoon — a provider choice you do not regret at 3am.
The hidden pricing costs nobody advertises
Per-page price is not the total cost of an extraction provider. The line items that never make it onto the pricing page:
- Concurrency limits. The difference between “100k pages in 2 hours” and “100k pages in 3 days” is a concurrency cap, not a price. A cheap provider with a hard concurrency ceiling can be more expensive than a pricier one that lets you burst.
- Minimum spends. Several “per-page” providers hide a minimum monthly commit behind the per-page number. ScraperAPI’s ~$49/mo for 5k requests is really a $9.80/1k price and a $49 floor.
- Credit expiry. Credit-based tiers sometimes expire unused credits monthly. Buy more than you use and you are donating to the provider.
- Overage pricing. Going over your plan tier is often priced 3–5x the in-plan rate, and auto-overage means you find out on the invoice, not before.
- The retry tax. If a provider fails 10% of the time and you retry those calls, your effective price is 10% higher than the sticker. Providers with better extraction quality have a lower hidden retry tax — which is another reason the 22-point yield gap is a price gap too.
The way to surface all of these: take your real monthly volume, your real retry rate, and your real concurrency needs, and compute effective cost-per-1k across the shortlist. The provider that wins the sticker-price comparison is frequently not the one that wins that number.
From extraction to answers: the full RAG pipeline
Extraction is a means to an end, and the end is almost always the same: feeding an LLM the right text. So let me show the full chain, because the extraction decision ripples through everything downstream of it.
The pipeline, in order:
- Discover — a crawler or a sitemap hands you a list of URLs.
- Extract — this guide’s subject. URL → clean markdown.
- Chunk — split the markdown into overlapping chunks (~500–800 tokens each, ~10–15% overlap so sentence boundaries and context survive the split).
- Embed — turn each chunk into a vector.
- Index — store vectors with metadata (URL, title, date, section).
- Retrieve — on a query, find the most similar chunks.
- Answer — feed the retrieved chunks to an LLM as context.
The extraction step’s quality determines the ceiling of everything below it. Three ways bad extraction corrupts this chain:
The nav-vector problem. Boilerplate that bleeds into your output gets embedded. Your vector store now has embeddings for “Sign up for our newsletter” and “© 2026 All rights reserved.” Retrieval starts matching on nav text, and your answers start citing your own cookie banner. The fix is at the extraction step — you cannot clean it out of a vector store without re-embedding everything.
The token-budget multiplier. The chunker chunks whatever you give it. Give it 70,000 tokens of raw HTML and you get ~100 chunks of garbage per page instead of ~6 chunks of prose — 16x the embeddings, 16x the vector-storage cost, 16x the retrieval noise. The extraction step is the cheapest place to compress, and every downstream system pays for your decision to skip it.
The completeness trap. A “successful” extraction of a page that lost half its content produces a RAG system that confidently answers from a truncated corpus. It does not tell you it is truncated. The only defense is the output-length sanity check from the integration section, applied to every page, every run.
Here is the token budget for a working system, so the numbers are concrete. Say you index 10,000 articles a month:
- 10,000 pages × ~3,000 clean tokens = 30M tokens of indexing content per month.
- At ~$0.15/1M embedding input (mid-tier) that is ~$4.50 in embedding costs — negligible.
- The same 10,000 pages as raw HTML would be 700M tokens — ~$105, and 23x the vector storage, and retrieval that matches markup instead of meaning.
The extraction call is the smallest line item in this budget, and it controls every larger one. This is the sentence to take away: extraction is 5% of the RAG budget and 100% of the RAG quality. Underfund it and the other 95% silently underperforms.
War stories: how extraction dies in production
Every pattern in this guide is a scar from a real incident. Let me tell you the three most instructive ones, because the failure modes are always the same and always embarrassing:
The 200-word SPA. A team built a “chat with our docs” product against a documentation portal that was a React SPA — every page was a <div id="root"> shell. Their extraction provider fetched without rendering, the pipeline “worked,” and the product returned 200 words of “Loading…” for every question. The docs had 2,000 pages; the vector store had ~2,000 chunks instead of ~12,000. The fix was one flag — render the page — and a re-index. The lesson: if your provider does not render by default, your pipeline is silently truncating every SPA it touches.
The redesign drift. A price-monitoring scraper ran fine for eight months on a retail site. The site redesigned, its product HTML went from <div class="price"> to a Vue-rendered component with no stable selector, and the extractor started returning the page’s “recommended for you” carousel as the “product.” The team caught it because their yield monitor dropped from ~1,200 tokens per page to ~150. Without the monitor, the pricing data would have been wrong for weeks. The lesson: extraction quality decays; you need a yield chart, not a prayer.
The soft-404 flood. An aggregation pipeline hit a site that started returning HTTP 200 with “This page has moved” for its old article URLs. The pipeline, trusting status codes, ingested ~40,000 soft-404 pages into its corpus. Retrieval started returning “This page has moved” as answers. The lesson: never trust HTTP 200; trust the content. A 30-word length check on every extraction would have caught all 40,000.
The common thread is not bad luck — it is silent failures. Extraction fails in ways that look like success: plausible token counts, valid-looking markdown, 200 status codes. The defense is structural: render by default, length-check every output, monitor yield per URL pattern, and treat a drop in median tokens as a production alert. Build those three checks and you have de-risked the entire layer.
Beyond extraction: the adjacent tools
Extraction is one layer of a stack, and knowing where it ends keeps you from buying the wrong thing. The boundaries, drawn sharply:
- Extraction API — one URL in, clean content out. This guide.
- Crawler API — many URLs in, a site’s pages out. Extraction plus link traversal and a queue. If your job is “the whole site, all 40,000 pages,” you want a crawler, not an extractor. (We have a dedicated guide to web crawler APIs.)
- Search API — a query in, relevant URLs out. Extraction answers “what is on this page?”; search answers “which pages answer this question?” They compose: search finds the URLs, extraction reads them. (See the search API comparison and the best AI search APIs for RAG.)
- Agentic search / deep research — a question in, a researched answer out. The agent runs search + extraction + synthesis for you, which is precisely why extraction quality is the floor under every “agentic” product. An agent is only as good as the pages it can read. (More in agentic search vs RAG.)
The composition matters because most “AI” products use all four. The search call finds candidates; the extraction call reads them; the LLM synthesizes. If your extraction is the weak link, your agent is an expensive machine for producing 200-word answers from empty pages.
The decision guide
By now you have the pieces. Here is the synthesis:
- RAG pipeline or LLM context at volume → Keirolabs /search/content or /extract. Clean markdown, JSON schema, JS rendering, ~$0.75/1k — the cheapest one-call path to LLM-ready text, with 500 free credits to prove it on your own pages.
- A URL transform with zero setup → Jina Reader.
r.jina.ai/prefix, free, done in a minute. The lazy man’s extraction, and I mean that as a compliment. - JS-heavy SPA where rendering is the hard part → Firecrawl. Renders by default, best-in-class markdown, 1,000 free credits to test the hardest sites on your list.
- Bot-protected or premium targets → ScraperAPI or Apify. Residential proxies and CAPTCHA handling are the point; the per-call premium is what you pay for the harder job.
- A repeatable complex scrape → Apify actors. Rent a maintained solution for a specific site instead of building one.
- No-code / non-technical → webscraper.io or Browse.ai. Point and click; you are paying for the UI.
- Small volume, engineering time is cheap, you like pain → the self-host stack. Read the crossover chart first.
And the process, which matters more than the pick: prototype on free credits, measure extraction quality on your own target URLs, sanity-check output length on every call, add a render fallback for the hard 20%, and price at your real monthly volume. Do that and whichever provider you choose will work. Skip it and the cheapest provider will cost you the most.
The 2026 market: who is actually winning
Extraction is a young market that has already consolidated into a recognizable shape. The players, in rough order of mindshare:
Firecrawl owns the “AI stack” developer mindshare. It is the extraction API that shows up in every LangChain/CrewAI tutorial, and its 1,000 free credits have made it the default prototyping tool for a generation of AI builders. It wins on polish, ecosystem, and the “crawl/search/scrape/map” all-in-one story — not on raw price.
Jina Reader owns the “instant transform” moment. r.jina.ai/ is a genuinely brilliant product trick: zero auth, works in a URL bar, no SDK. It has become the go-to for the 100-page job and for quick prototypes. Its weakness is the opposite of Firecrawl’s: it is not built for the 100k-page job.
ScraperAPI owns the bot-fighting niche. Any team whose targets sit behind Cloudflare ends up here eventually. It is not really competing with Firecrawl for the RAG crowd; it competes with the proxy vendors.
Apify owns the marketplace model. The actor economy is real — someone has already written a scraper for whatever site you need. It is the answer to “I want a maintained solution for this specific site,” and the wrong answer for “give me clean markdown from arbitrary URLs.”
Keirolabs is the price-disruptor position. Flat $0.25/1k credits, 3 credits per extraction, JS rendering included, structured output included — a genuinely different cost curve from the incumbents. It is the answer to “I have volume and I do not want to pay the developer-tool markup.” Its gap is ecosystem and mindshare, which is precisely the gap a price advantage can close when the category commoditizes.
The market’s trajectory is visible in that list: the differentiation is migrating from “who extracts best” to “who extracts cheaply and reliably at scale.” Extraction quality has converged — the good providers are all within a few points of each other on most pages, and the 22-point gap in my audit was mostly explained by failure-handling, not algorithm. When quality converges, price and operations decide. That is a great place to be if you are the price leader, and a hard place if you are not.
The operational layer: latency, reliability, and the SLO you actually need
Every provider publishes a latency number. Almost none publish the number that matters: the p95 latency under load, and the uptime when the web is being mean to them. Here is the operational reality, in the order it will bite you:
Latency. A single extraction’s latency is the sum of fetch + render + extract + structure. On a fast server-rendered page that is ~150–400ms; on a heavy SPA with rendering it is 1.5–4s; with an LLM pass it is 3–6s. The provider’s median latency is marketing; the p95 is what your users feel. Ask for it, and ask what happens under concurrency — most providers’ latency doubles when you parallelize, because rendering is compute-bound and their fleet is sized for average traffic, not your burst.
Uptime. Extraction APIs fail in a distinctive way: not the whole API down, but specific targets failing — a site blocks them, a proxy pool goes stale, a render fleet saturates. A provider that is 99.9% “up” can still be effectively down for your specific URLs for a week. The mitigations are on your side: retries, fallbacks, and a second provider as a failover for your critical paths. The “two providers” pattern is worth the integration cost for anything you depend on.
Rate limits are a product feature. The free tiers are rate-limited by design — they are marketing, not infrastructure. When you move to production, the rate limit you negotiated (or that the plan grants) is your throughput ceiling, and it is the least-negotiable number on the pricing page. If your backfill needs 50 pages/second and the provider’s top tier gives you 10, no amount of engineering fixes it. Check the limit before you sign, not after.
The SLO that matters for a production pipeline is not “the API is up” — it is “my extraction of target X succeeds with full content within Y seconds, at least Z% of the time, this week.” Everything else is noise. That is the number to negotiate and monitor, and it is the number that makes the difference between a $0.75/1k provider and a $20/1k provider disappear — or become a bargain, depending on who meets it.
A 12-month roadmap: from prototype to production extraction
If you are starting a pipeline that reads the web, here is the roadmap that avoids the failure modes in this guide. It is deliberately boring:
Month 1 — Prove it on your pages. Take the free tier of the two or three providers that fit your use case (from the decision guide). Run the 50-page audit from earlier. Pick the one that wins on your URLs, not the demo. Target: one provider, a documented quality score, zero dollars spent.
Month 2 — Wire the pipeline. Connect the extractor to your chunker, embeddings, and vector store. Add the production patterns from earlier: retries, backoff, the render fallback, and the output-length sanity check on every call. Target: a working end-to-end pipeline on a test corpus, with yield monitoring on a chart.
Month 3 — Measure the real economics. Compute your true effective cost per 1k at your real volume — including retries, overages, concurrency limits, and the LLM token bill downstream. Re-run the provider comparison at this number, not the sticker. Target: a signed-off unit cost you can budget against.
Months 4–6 — Scale with a safety net. Push to production volume with monitoring on yield and latency. Add a failover provider for your critical URL patterns — not a full second integration, just a fallback call when the primary fails. Target: extraction success rate >99% on your monitored targets, with the 200-word silent failures caught by the yield monitor.
Months 7–12 — Re-audit and re-price. Re-run the 50-page audit quarterly (sites redesign; rankings drift). Re-negotiate volume pricing at your now-proven volume. If you have grown past ~500k pages/month and have an owner for the infrastructure, start the self-host crossover math in earnest. Target: your extraction layer is a line item you can defend, not a 3am incident you dread.
The whole roadmap has one through-line: the choice is made on your URLs, at your volume, under your failure conditions — never on a free tier, never on a demo. Everything else in this guide is detail. That is the discipline that separates the teams that treat extraction as infrastructure from the teams that treat it as a rounding error, and it is the entire difference between a pipeline that answers well and one that answers with nav text.
Glossary: every term in this guide, decoded
For the glossary-of-record, here is every concept from this guide in one place:
- Extraction API — turns one URL into clean content (markdown/JSON/text) in one call.
- Crawler API — extraction plus link traversal and a queue; turns a site into many URLs.
- Readability heuristic — the classic DOM-scoring algorithm (Arc90, 2009) that finds the main content by text density, link density, and tag semantics.
- DOM model — a classifier trained on labeled page structures to recognize “article” vs “nav” beyond what a heuristic can.
- LLM pass — feeding candidate content to an LLM to extract/clean; most accurate, slowest, most expensive.
- Boilerplate bleed — nav/footer/ads leaking into extraction output; silently corrupts RAG.
- Soft 404 — a page that returns HTTP 200 but is really an error page; poisons corpora.
- JS rendering / headless browser — running the page’s JavaScript (via Playwright/Puppeteer) before extraction; the “rendered mode” premium on pricing pages.
- json_schema mode — structured output: you declare fields, the API returns a JSON object; one call instead of a five-step extract→parse→re-prompt pipeline.
- Yield — the fraction of a page’s true content that makes it into the output; the quality metric that matters.
- Token bomb — feeding raw HTML to an LLM instead of clean extraction; ~23x the input tokens and cost.
That is the whole vocabulary. If you take nothing else from this guide, take this: extraction is 5% of the RAG budget and 100% of the RAG quality, the good providers have converged, and the decision is made on your URLs at your volume — so spend the afternoon running the audit and never look back.
The 22-point gap, quantified
The gap between the best and worst extractor on my 50-page audit was 22 points of usable yield. Numbers like that feel abstract, so here is the same result broken down by page type — where the winners won and where everyone lost:
| Page type | Best provider yield | Worst provider yield | Gap | The reason |
|---|---|---|---|---|
| Server-rendered blog | 96% | 84% | 12 | Even easy pages get boilerplate bleed from the worst extractors |
| React SPA (rendered) | 91% | 21% | 70 | Non-rendering providers get a shell, not an article |
| Documentation portal | 94% | 61% | 33 | Heavy nav/toc structures fool weak heuristics |
| Long-form news feature | 89% | 52% | 37 | Multi-part, image-heavy layouts trip the content guess |
| Product page (schema) | 93% | 74% | 19 | Schema helps everyone, but not equally |
The aggregate 22 hides a much uglier distribution: on the hardest 20% of pages, the gap is 70 points, not 22. The providers that win the overall audit do so because they render by default and fall back gracefully — not because their heuristic is fundamentally smarter. And notice the second row: a provider that does not render JavaScript does not just lose a few points on SPAs — it loses 70. That single row is why “renders by default” is the first box on any extraction provider’s checklist, and why this guide keeps coming back to it.
The equally uncomfortable finding: no provider was best on every page type. The leader on the server-rendered blogs was not the leader on the SPAs. If your workload is narrow (all news pages, say), the “best overall” provider may not be your best — which is the argument for running the 50-page audit on your specific mix rather than trusting an aggregate score, no matter how well it was measured.
That table is also why the recommendation structure of this guide is what it is: the volume-price provider for the common case, the render-everything provider for the hard SPAs, and the bot-fighter for the protected pages. No single provider wins all three rows today, and the ones that try usually lose the price row to do it.
The opinion
Extraction is the quiet backbone of every AI system in 2026, and it is the most under-invested layer in the stack. Everyone wants to talk about the model. Nobody wants to talk about turning a URL into clean text — until it breaks, at 3am, in production. I have been that 3am call more times than I care to count, and every single time the root cause was the same: someone trusted a provider’s demo instead of running it on their own pages.
Let me be straight about the tension in this guide, because you deserve it. I run extraction pipelines for a living, and I have a bias toward the providers that have actually held up under my workloads. Keirolabs is the one that has held up cheapest for me, and I have said so plainly. That is not a neutral position, and I am not going to pretend it is. What I have tried to do instead is give you the method — the 50-page audit, the yield metric, the token math, the hidden-cost checklist — so you can verify my conclusion on your own URLs rather than take it on faith. If you run the audit and a different provider wins on your pages, you should use that provider. The method is the point; my pick is just where the method landed for me.
Three predictions, since this is 2026 and I am allowed an opinion:
Three predictions, since this is 2026 and I am allowed an opinion:
- Structured extraction will eat plain extraction for the fielded-data use cases. Once a team realizes it can skip the extract-then-parse pipeline, it does not go back.
json_schemais the wedge; the “one call, clean object” pattern is the new default for price monitoring and catalog work within two years. - The LLM pass will keep getting cheaper until it is nearly free to overuse. Token prices are falling 10–20x a year. The day an LLM pass costs less than a heuristic’s engineering-time cost, every extractor becomes “LLM-first” — and the differentiation shifts to rendering and structured-output reliability, which are the hard operational parts nobody has solved yet.
- JS rendering stops being a paid tier and becomes table stakes. The web is majority client-rendered; charging extra for the thing everyone needs is a holding pattern, not a business model. The providers that bake rendering into the base price (and the ones with the cheapest render fleet) will win the volume buyers.
Pick the provider that fails the least on your actual targets — not the one with the best demo — and the whole stack above it gets cheaper and more reliable overnight. That has been the whole guide in one sentence.
About the author
Dave Martin has been building web-extraction and RAG pipelines since 2019 — first self-hosted with Readability.js and Playwright, then across every major extraction API. He has run extraction at volumes from 10,000 to 10 million pages a month, and has been woken up by every failure mode in this guide at least once. He writes about the unglamorous parts of the AI stack — the parts that quietly decide whether the glamorous parts work.
Keep reading
Frequently Asked Questions
What is the best website content extraction API in 2026?
For clean markdown from a URL, Firecrawl and Jina Reader are the two defaults, and both have generous free tiers. Firecrawl scrapes with full JS rendering and returns structured markdown/JSON (1,000 free credits/mo); Jina Reader adds 'r.jina.ai' in front of any URL and returns clean text (free tier available). Keirolabs /extract and /search/content return the same clean page text with a 500-credit free tier and cheaper volume pricing.
What is the difference between a content extraction API and a crawler API?
Extraction is single-URL: you hand it one URL, it returns that page's clean content as markdown, JSON, or plain text. Crawling is multi-page: you hand it a site or seed list and it follows links across pages. Extraction is the building block; crawling is extraction plus link traversal and a queue.
How does URL-to-markdown extraction work?
The API fetches the page, strips navigation, footers, ads, and scripts, then converts the remaining article body into clean markdown or JSON. Most services use readability-style algorithms plus an LLM pass or a trained DOM model to identify the main content. JS-rendered sites need a headless browser step, which is why pricing jumps for 'rendered' mode.
What is the cheapest website content extraction API?
Keirolabs /extract is about $0.75 per 1,000 extractions at full price (3 credits each, $0.25/credit) with 500 free credits/mo. Jina Reader has a free tier and starts around $20/1k pages on paid plans. Firecrawl is roughly $1.60–3.20 per 1k on Hobby depending on credit usage. ScraperAPI starts at $49/mo for 5k extractions (~$9.80/1k).
Which content extraction API handles JavaScript rendering best?
Firecrawl and Apify render JavaScript by default in their base scrape, so SPAs and client-rendered pages extract correctly without configuration. Jina Reader handles most JS via its rendering pipeline but is less predictable on heavy apps. Keirolabs /extract covers JS in its 3-credit call. In my testing, ScraperAPI priced JS rendering as a separate premium add-on, which roughly doubled the effective per-call cost.
Can a content extraction API replace reading a page myself?
For most article, blog, and documentation pages, yes — the extraction API returns the main content in seconds, cleaner than a raw HTML parse. It fails on pages with content behind login walls, aggressive bot protection, or paywalls. For those, you still need a human or a premium scraping provider.