Every page you fetch has a cost, and the cost gap between readers is large. A plain HTTP client such as curl, requests or fetch downloads bytes and hands you the response body. A headless browser launches a real engine, parses HTML, executes scripts, resolves styles and often loads dozens of subresources before the DOM settles. A PDF parser reads a byte stream and reconstructs characters and lines from drawing instructions.
That ordering is also the order of reliability. The cheapest reader that returns clean text is the one you should try first, and the browser is a fallback rather than a default. The reason is simple: server-side rendering sends the content in the first response, so a single request is enough to read it, while client-side rendering builds the page after the response arrives, and an HTTP client alone will not see data that appears only after scripts run (Browserless).
A useful mental model separates three jobs that people often blur together. Crawling decides which pages to visit, scraping collects content from a page, and extraction maps values into fields. Each has its own failure mode, and a pipeline can reach every URL while still extracting the wrong value, or extract perfect records from only part of the intended set (webscraper.io). Reader choice is a scraping decision, quality scoring is an extraction decision, and you should measure them separately.
Keep the default policy blunt:
- If the response body is a PDF, send it to the PDF parser.
- If the body is HTML with the target text in the initial response, keep the HTTP result.
- If the body is a thin shell, an empty app root, or a script-only stub, escalate to a headless render.
- If any reader produces text that fails the quality gate, escalate one level and record the failure.
The rest of this article fills in how to classify, how to score, and what the cost looks like with numbers.



