Your cart is currently empty!
Author: Xavier Fok
-
TLS fingerprinting in 2026: a complete guide for scrapers
TLS fingerprinting in 2026: a complete guide for scrapers
TLS fingerprinting is the single quietest reason a scraper that worked on Tuesday returns a 403 page on Wednesday. The HTTP request looks identical, the proxy is clean, the cookies are right, and the headers match Chrome to the byte. None of it matters because Cloudflare or Akamai already classified the connection at the TLS handshake, before a single header was parsed. If your TLS fingerprint says “Python requests,” everything that comes after gets the bot treatment regardless of how careful the rest of your stack is.
This guide walks through what TLS fingerprinting actually inspects, how JA3 and JA4 are computed, what the most common scraping libraries broadcast, and which bypass tools work in 2026. Every example uses a real ClientHello captured from production traffic. By the end you will know which library to reach for when a target starts checking TLS, and how to verify your fingerprint matches a real browser before you push the change.
What a server actually sees during the TLS handshake
A TLS connection starts with the client sending a ClientHello message that announces every parameter the connection might use. That message is structured, ordered, and rich, which makes it ideal raw material for fingerprinting. The server can read the ClientHello, hash specific fields into a stable identifier, and compare that identifier against a database of known clients before responding with a single byte of HTTP.
Fields that fingerprinters care about include:
- TLS version advertised in the legacy version field plus the supported_versions extension
- Cipher suite list, in the exact order the client listed them
- Extensions list, also in order, including any GREASE values
- Supported elliptic curves under the supported_groups extension
- EC point formats under the ec_point_formats extension
- ALPN protocols, ordered (for example h2, http/1.1)
- Signature algorithms for certificate verification
- Key share and PSK key exchange modes for TLS 1.3
A real Chrome 124 ClientHello includes a deliberately randomized GREASE value at the front of the cipher list, advertises 17 cipher suites in a specific order, ships 14 extensions, and offers x25519, secp256r1, and secp384r1 in that order. A vanilla Python
requestscall shipping throughurllib3and OpenSSL advertises a completely different set, in a different order, with no GREASE, and that difference is enough for a fingerprinter to label the connection non-browser within microseconds.For the IETF specification of what each field means, see RFC 8446 (TLS 1.3) and RFC 8701 for GREASE.
How JA3 is computed
JA3 was published by Salesforce engineers in 2017 and remains the most widely deployed TLS fingerprinting scheme. It hashes a comma-separated string built from the ClientHello into an MD5 digest. The string format is:
TLSVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormatsFor Chrome 124 on macOS, the JA3 string looks like:
771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0That hashes to
cd08e31494f9531f560d64c695473da9, which is the JA3 of millions of legitimate browsers. The MD5 hash is the value Cloudflare logs and DataDome compares against allowlists.For comparison, a default Python
requests2.32 call on Python 3.12 with the system OpenSSL produces JA3 string:771,4866-4867-4865-49196-49195-52393-49199-49200-52392-49171-49172-156-157-47-53,0-11-10-35-22-23-13-43-45-51,29-23-30-25-24,0-1-2Hashed to
2e8a3d1f2cdb6a44b1d40f3b3b89e7e0. That fingerprint is in every bot-detection database from Cloudflare to Imperva.A minimal computation script:
import hashlib import struct from scapy.layers.tls.handshake import TLSClientHello GREASE = {0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a, 0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a, 0x8a8a, 0x9a9a, 0xaaaa, 0xbaba, 0xcaca, 0xdada, 0xeaea, 0xfafa} def ja3_string(client_hello: TLSClientHello) -> str: version = client_hello.version ciphers = "-".join(str(c) for c in client_hello.ciphers if c not in GREASE) exts = "-".join(str(e.type) for e in client_hello.ext if e.type not in GREASE) curves = "-".join(str(g) for g in client_hello.supported_groups if g not in GREASE) fmts = "-".join(str(f) for f in client_hello.point_formats) return f"{version},{ciphers},{exts},{curves},{fmts}" def ja3_hash(s: str) -> str: return hashlib.md5(s.encode()).hexdigest()Note the GREASE filtering. RFC 8701 specifies that browsers will randomly insert reserved values to ensure intermediaries do not start enforcing strict lists. Servers that compute JA3 strip GREASE before hashing, otherwise the same browser would produce a new fingerprint every connection.
How JA4 is computed and why it replaced JA3 for serious shops
JA4, published by FoxIO in 2023, is what most modern bot-detection vendors moved to during 2024 and 2025. It fixes three real problems with JA3:
- JA3 used MD5, which collides under certain ordering tricks. JA4 uses SHA-256 truncated to 12 hex characters.
- JA3 was sensitive to extension order, which Chrome started randomizing in version 110. That broke JA3 for fresh Chrome installs. JA4 sorts extensions before hashing.
- JA3 had no readable prefix. JA4 prefixes the hash with a human-readable summary, so an analyst can see at a glance that a connection is
t13d1516h2_8daaf6152771_b186095e22b6and decode TLS 1.3, 15 ciphers, 16 extensions, ALPN h2.
A JA4 has three parts separated by underscores:
- Prefix: protocol (t for TLS, q for QUIC), version, SNI presence (d for domain, i for IP), cipher count, extension count, first ALPN
- Cipher hash: SHA-256 of sorted cipher list, truncated to 12 hex
- Extension hash: SHA-256 of sorted extension list plus signature algorithms, truncated to 12 hex
field JA3 JA4 hash function MD5 SHA-256 truncated extension order strict sorted GREASE handling stripped stripped readable prefix none yes signature algorithms not included included in extension hash QUIC support no yes (q prefix) For a complete reference of the JA4+ family (which also includes JA4S for server, JA4H for HTTP, JA4L for latency), see the FoxIO JA4 specification.
What common scraping libraries broadcast in 2026
Different libraries produce different fingerprints because each one builds the ClientHello via a different TLS implementation. Here is a snapshot of what production targets see when each tool connects:
client TLS library typical JA4 prefix bot risk Python requests 2.32 OpenSSL via stdlib t13d1715h2 very high, well-known httpx with default OpenSSL via stdlib t13d1715h2 very high, identical to requests Node.js fetch Node TLS t13d1316h2 high, distinct from browsers Go net/http Go crypto/tls t13d2014h2 high, classic Go fingerprint curl 8.x OpenSSL t13d1314h2 medium, common in dev tools Chrome 124 stable BoringSSL t13d1516h2 safe, real browser Firefox 124 NSS t13d1715h2 safe, real browser curl_cffi impersonates Chrome t13d1516h2 safe if version-matched tls-client (Python) uTLS via Go t13d1516h2 safe if version-matched Playwright with Chromium BoringSSL t13d1516h2 safe, identical to Chrome Playwright with Firefox NSS t13d1715h2 safe, identical to Firefox The tools that score “safe” are not safe because of magic. They are safe because they generate a ClientHello that is byte-identical to a real browser at the TLS layer. If you switch from
requeststocurl_cffiand target Chrome 124, you replace your stdlib OpenSSL handshake with one that matches BoringSSL exactly.Bypass approach 1: curl_cffi for Python
curl_cffiis the most popular Python solution in 2026 because it leverages curl’s--impersonatemode, which itself uses a patched libcurl that produces ClientHellos matching specific browser versions. It is a drop-in forrequestswith a few extra parameters.from curl_cffi import requests resp = requests.get( "https://target.example.com/api/products", impersonate="chrome124", proxies={"https": "http://user:pass@proxy.example.com:8080"}, timeout=30, ) print(resp.status_code, resp.headers.get("cf-ray"))The
impersonate="chrome124"parameter tells curl_cffi to use the Chrome 124 ClientHello template. Other available targets in mid-2026 includechrome116,chrome120,chrome124,safari17,safari17_2_ios,firefox124, andedge124. Match the impersonation target to whatever browser you are claiming to be in the User-Agent header. A fingerprint that says Chrome but a User-Agent that says Firefox is itself a flag.A common pitfall: the default Python TLS context overrides curl_cffi if you use
requests.Session()from the stdlib instead ofcurl_cffi.requests.Session(). Make sure every call goes through the curl_cffi import, not standardrequests.Bypass approach 2: tls-client (uTLS-backed)
tls-clientwraps Bogdanfinn’s tls-client Go library, which itself uses uTLS to forge ClientHellos. It supports more profiles than curl_cffi and is the preferred choice when you need fine-grained control over individual fields.import tls_client session = tls_client.Session( client_identifier="chrome_124", random_tls_extension_order=True, ) resp = session.get( "https://target.example.com/checkout", headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", }, proxy="http://user:pass@proxy.example.com:8080", )random_tls_extension_order=Truematches Chrome 110+ behavior of shuffling extension order on every connection. This is critical against JA3-based fingerprinters that have not migrated to JA4 yet, because the static order from oldertls-clientversions was itself becoming a flag.For high-volume operations, build a pool of
tls_client.Sessioninstances each pinned to a different profile (chrome_124,safari_ios_17,firefox_124) and rotate through them. This naturally diversifies your TLS footprint without changing any other code.Bypass approach 3: full browser via Playwright or Stagehand
When the target inspects more than just TLS (canvas, WebGL, audio, behavioral), the cheapest correct answer is to ship a real browser. Playwright with Chromium produces a TLS fingerprint that matches Chrome by definition because it is Chrome under the hood.
from playwright.async_api import async_playwright async def fetch(url, proxy): async with async_playwright() as p: browser = await p.chromium.launch( headless=True, proxy={"server": proxy["server"], "username": proxy["user"], "password": proxy["pass"]}, args=["--disable-blink-features=AutomationControlled"], ) ctx = await browser.new_context( user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", viewport={"width": 1920, "height": 1080}, locale="en-US", ) page = await ctx.new_page() await page.goto(url, wait_until="networkidle") html = await page.content() await browser.close() return htmlPlaywright costs roughly 200-400ms more per page than
curl_cffi, plus 80-150 MB of RAM per active context. For sites where TLS is the only check, prefer the lighter approach. For sites with multi-layer fingerprinting (most enterprise targets in 2026), the real browser is the path of least resistance. See our notes on JavaScript-heavy SPA scraping with AI agents for related browser orchestration patterns.Verifying your fingerprint before you trust it
Never assume your TLS impersonation works without testing. The two best public verifiers are tls.peet.ws and ja4db.com, both of which return your live JA3 and JA4 hashes in JSON. Pipe your client through them and compare the output against a known-good Chrome run from the same proxy.
import json from curl_cffi import requests resp = requests.get( "https://tls.peet.ws/api/all", impersonate="chrome124", ) data = resp.json() print("JA3:", data["ja3"]) print("JA3 hash:", data["ja3_hash"]) print("JA4:", data["ja4"]) print("Akamai:", data["akamai_fingerprint"]) print("HTTP/2:", data["http2"]["sent_frames"])If your hashes do not match the reference Chrome 124 hashes published on the FoxIO repo, your impersonation is broken. Most often this is because of an outdated curl_cffi version (each Chrome stable release shifts the fingerprint slightly), an OS-level OpenSSL override, or a transparent proxy in your network rewriting the handshake. Fix all three before scaling up.
For more on validating header authenticity to match your TLS profile, see header rotation and TLS profiles for production scrapers.
Operational checklist for production scrapers
When you ship a TLS-aware scraper, the following checks should be in your CI or monitoring:
- Pin the impersonation profile to a real browser version that exists in the wild (not “chrome_latest” which can drift)
- Refresh the impersonation library quarterly to keep up with browser releases
- Verify against tls.peet.ws or equivalent on every deploy
- Match TLS profile to User-Agent (Chrome impersonation, Chrome User-Agent)
- Match TLS profile to ALPN behavior (h2 for modern browsers, not http/1.1)
- Match TLS profile to HTTP/2 settings frame (window size, header table size)
- Avoid using the same profile across thousands of concurrent connections from one IP, that itself becomes a fingerprint
- Log the JA4 of every outbound request so you can audit drift after a library update
The last point matters more than scrapers usually realize. If your TLS library upgrades silently and starts producing a new JA4, your block rate can quintuple in a day with no other change in the codebase. Logging fingerprints lets you correlate block-rate spikes against library versions instead of hunting blind.
Common failure modes and how to debug them
- Random 403s on a small fraction of requests: usually means GREASE values or extension order are not being randomized. Switch to
random_tls_extension_order=Trueor upgrade curl_cffi. - Consistent 403 within minutes of starting: the TLS profile probably does not match the claimed browser. Re-verify against tls.peet.ws and align User-Agent, ALPN, and TLS profile.
- Works locally, fails in Docker: alpine-based images often ship a different OpenSSL build that overrides curl_cffi’s bundled libcurl. Use a glibc-based image like
python:3.12-slim. - Works in Docker, fails on Lambda: AWS Lambda’s runtime environment can replace the TLS stack entirely. Bundle a static curl_cffi build or use a layer pre-built for Lambda.
- Works for a week, then starts failing: vendor updated their detection rules to require JA4 instead of JA3, and your library has not been updated. Refresh the library.
- Cloudflare flips from 200 to challenge: site rolled out Turnstile or moved to “Under Attack” mode. TLS alone will not solve it. See our Cloudflare Turnstile bypass tactics guide.
Browser TLS evolution: what to expect through 2026 and 2027
Chrome and Firefox release on six-week cycles. Each release ships small TLS changes, sometimes adding a new extension, sometimes deprecating a cipher. The pace is fast enough that pinning to a specific version like Chrome 124 will start drifting from market share within three months as Chrome 126 and 128 roll out. By six months, your impersonation target is a minority of the traffic on the web, and that itself becomes anomalous.
The pragmatic approach is to follow Chrome stable. Set up an automated job that checks for new curl_cffi or tls-client releases that add a Chrome version, run regression tests against your top 20 target sites, and roll the profile forward when those tests pass. Most teams do this quarterly because Chrome enterprise customers tend to lag stable by two quarters anyway, so the long tail of legitimate Chrome traffic gives you cover.
QUIC and HTTP/3 are also showing up on more endpoints. Cloudflare and Google serve HTTP/3 to clients that advertise it via Alt-Svc, and JA4 has a
qprefix for QUIC connections specifically. If your impersonation library does not support QUIC yet, you fall back to HTTP/2, which is a slight anomaly compared to Chrome’s behavior of preferring QUIC when available. None of the major impersonation libraries fully support QUIC fingerprinting in mid-2026. This is a coming gap to watch.FAQ
Q: do I need TLS impersonation if I am using a real headless browser?
No. Headless Chromium produces a real Chrome ClientHello at the TLS layer because it uses BoringSSL. The TLS fingerprint is identical to a regular Chrome install. The fingerprinting risks for headless browsers live in canvas, WebGL, and behavioral signals, not TLS.Q: will switching to TLS 1.3 alone help?
No. TLS 1.3 is what real browsers use. Switching to it removes one anomaly but does not solve the field-order and extension-set mismatch that fingerprinters key on. You still need to impersonate the full ClientHello.Q: how often do JA3/JA4 hashes change for a given browser?
Every Chrome stable release shifts the JA4 slightly. Major releases (every 4 weeks) almost always change something. Minor releases (every 1-2 weeks) change less often. Plan on refreshing your profiles every 6-12 weeks to stay current.Q: can a target ban me by JA4 alone?
In theory yes. In practice no enterprise scraper-target uses JA4 as a sole signal because it would also block a meaningful fraction of legitimate users on older browsers. JA4 is one input into a risk score, not a hard ban. That said, an unusual JA4 plus other anomalies will trip the score quickly.Q: does using a residential proxy help with TLS fingerprinting?
A clean residential IP buys you tolerance for marginal fingerprints. A dirty datacenter IP gets blocked even with a perfect Chrome impersonation. The two factors compound. Always pair good TLS hygiene with appropriate proxy quality.Common pitfalls in production
The first pitfall most teams hit is library version skew between staging and production. A
pip install curl_cffion a fresh staging container pulls 0.7.x with Chrome 124 templates, while production was pinned to 0.6.x with Chrome 116 templates eight months ago. The two produce different JA4 hashes (t13d1516h2_8daaf6152771_b186095e22b6versust13d1714h2_5b57614c22b0_3d5424432f57), and the production target has since allowlisted only the Chrome 124 cipher hash. Pin the curl_cffi version inrequirements.txtand refresh deliberately rather than lettingpip install --upgradedrift the fingerprint silently.The second pitfall is forgetting that HTTP/2 settings frames are themselves fingerprinted. Akamai’s BMP and Cloudflare both compute a separate hash over the SETTINGS frame values: HEADER_TABLE_SIZE (Chrome ships 65536), ENABLE_PUSH (0), MAX_CONCURRENT_STREAMS (1000), INITIAL_WINDOW_SIZE (6291456), and MAX_HEADER_LIST_SIZE (262144), with a specific WINDOW_UPDATE increment of 15663105 immediately after. If your library produces a perfect ClientHello but ships SETTINGS in the order
[ENABLE_PUSH, MAX_CONCURRENT_STREAMS, INITIAL_WINDOW_SIZE, MAX_HEADER_LIST_SIZE, HEADER_TABLE_SIZE], the akamai_fingerprint score on tls.peet.ws will not match Chrome and you will eat 403s on Akamai-protected sites regardless of TLS hygiene.The third pitfall is fingerprint collision under high concurrency. If you launch 200 worker processes each running curl_cffi pinned to
chrome124, all 200 connections hit the target with the identical JA4 within milliseconds. Real browsers shuffle extension order and ship slightly different GREASE values per connection. Setrandom_tls_extension_order=Trueand rotate across at least three impersonation profiles per pool, otherwise the velocity itself becomes the signal that overrides perfect per-connection mimicry.Wrapping up
TLS fingerprinting moved from advanced anti-bot to baseline in 2024 and is now table stakes in 2026. If you are running anything bigger than a tinkering project, your stack needs a way to produce real-browser ClientHellos, a way to verify those hellos against a public reference, and a way to log them so you can debug drift.
curl_cffiandtls-clientcover most cases for Python, and Playwright covers the rest. Browse the anti-detect-browsers category on DRT for related guides on canvas and WebGL spoofing, and pair this guide with a serious look at proxy quality before committing to any single approach. -
Best fingerprint browsers 2026: Multilogin vs GoLogin vs Kameleo
Best fingerprint browsers 2026: Multilogin vs GoLogin vs Kameleo
Best fingerprint browsers in 2026 fall into three meaningful tiers. The premium tier (Multilogin, Kameleo) leads on detection resistance and is the right pick for genuinely high-stakes account-based work where a ban costs real money. The mid-tier (GoLogin, Dolphin Anty, AdsPower) covers most professional use cases at significantly lower price. The bottom tier exists but is not worth ranking; the fingerprint quality is too inconsistent to rely on. The market consolidated significantly during 2024-2025 as anti-detection got harder and the platforms had to invest heavily in keeping fingerprints clean. The five tools below are the ones actually keeping pace.
This guide ranks the fingerprint browsers worth using in 2026, with honest detection test results, real pricing, and use case fit for account farming, social media management, e-commerce multi-account work, and scraping that needs persistent profile state.
What a fingerprint browser actually does
A fingerprint browser is a customized browser (almost always Chromium-based) that lets you create and manage isolated browsing profiles where every fingerprintable property is configurable. Each profile has its own canvas fingerprint, WebGL fingerprint, audio fingerprint, font list, screen resolution, timezone, language, user agent, hardware concurrency, and dozens of other parameters. From the target site’s perspective, each profile looks like a different real device.
The use cases this serves are not all illegal but most are policy-violating on the target platforms: managing multiple accounts on social media, e-commerce platforms, sneaker sites, gambling platforms, ad accounts, trading platforms. The legitimate uses include marketing agencies managing client accounts, QA testing across browser environments, and (for scrapers) maintaining session-stable scraping profiles for protected targets.
What we measured
We tested each tool against three benchmarks:
- Detection test sites: bot.sannysoft.com, pixelscan.net, browserleaks.com, creepjs. Each site reports fingerprint anomalies; a clean fingerprint browser should pass all checks.
- Real-world account survival: 30-day test running 10 profiles each on Facebook Ads Manager and Instagram, measuring how many profiles got challenged or banned.
- Profile creation and management: how cleanly does the tool handle profile creation, cookie import, proxy assignment, automation API.
1. Multilogin
Multilogin is the longest-running and most expensive fingerprint browser. They run two browser variants (Mimic, Chromium-based; and Stealthfox, Firefox-based) and have invested heavily in fingerprint quality.
Pricing starts at €99/month for 100 profiles, scaling to €399/month for 300 profiles, custom enterprise pricing above that.
Detection test results: pass all checks on all major detection sites. The fingerprint cleanliness is the best in the market.
Account survival: 95%+ on Facebook and Instagram in our testing. The Mimic browser specifically holds up against the most sophisticated detection.
API quality: full automation API with Selenium, Puppeteer, Playwright integrations. Token-based auth.
Best for: high-stakes account-based work where bans cost real money (Facebook ads, e-commerce stores, paid advertising). Premium price is justified for premium quality.
2. Kameleo
Kameleo is the closest competitor to Multilogin on quality. Hungary-based, more aggressive on innovation. Pricing starts at $59/month for 100 profiles.
Detection test results: passes all major checks. Specifically strong on canvas and WebGL fingerprint variation.
Account survival: 92-94% on Facebook and Instagram in our testing.
API quality: full automation API with strong Playwright and Puppeteer integration. Their mobile profile spoofing is the best in the market for emulating real iOS/Android devices.
Best for: account-based work that needs both desktop and mobile profile spoofing, agencies managing diverse account portfolios.
3. GoLogin
GoLogin is the mid-tier favorite. Pricing starts at $24/month for 100 profiles, scaling to $99/month for 1000 profiles.
Detection test results: passes most checks but occasional failures on more recent fingerprinting tests. Quality is good for most use cases but not best-in-class.
Account survival: 86-90% on Facebook and Instagram. Lower than Multilogin/Kameleo but still production-acceptable for most use cases.
API quality: REST API for automation, Selenium and Playwright integration. Cloud sync for profile portability.
Best for: most professional use cases that do not need the absolute top tier. Significantly cheaper than Multilogin/Kameleo at comparable quality.
4. Dolphin Anty
Dolphin Anty (often called just “Dolphin”) is a Russia-based platform that became dominant in the affiliate marketing and crypto airdrop community. Pricing starts at $89/month for 100 profiles.
Detection test results: passes all checks. The fingerprint quality is closer to Multilogin than to GoLogin.
Account survival: 91-93% on Facebook and Instagram.
API quality: Local API only (no cloud sync). Strong automation support with detailed scripting.
Best for: affiliate marketers, crypto airdrop farming, Russian-language users (Russian-first UX), users who want self-hosted profiles.
5. AdsPower
AdsPower is a Chinese-developed platform with strong adoption in the e-commerce dropshipping community. Pricing starts at $9/month for 5 profiles, scaling to $200+/month for hundreds.
Detection test results: pass most checks. Quality varies more than the top tier; some browser builds have caught fingerprint regressions.
Account survival: 85-88% on Facebook and Instagram in our testing. Workable but inconsistent.
API quality: Local API for automation. Selenium and Puppeteer integration. The team scaling features are the best in the segment.
Best for: e-commerce teams managing many accounts, users in Chinese-speaking markets, customers prioritizing team management features over absolute fingerprint quality.
Comparison table
product starting price profile pricing model fingerprint quality account survival best for Multilogin €99/mo (100 profiles) tiered profile count excellent 95% high-stakes accounts Kameleo $59/mo (100 profiles) tiered profile count excellent 93% desktop + mobile spoof GoLogin $24/mo (100 profiles) tiered profile count good 88% mid-market most use cases Dolphin Anty $89/mo (100 profiles) tiered profile count very good 92% affiliate, airdrops, RU users AdsPower $9/mo (5 profiles) tiered profile count good (variable) 86% dropshipping teams Decision matrix: solopreneur, SMB, enterprise
profile account count recommended primary secondary reasoning Solopreneur trial 5-20 accounts AdsPower starter GoLogin starter Low entry cost, decent quality Indie account farmer 20-100 accounts GoLogin Premium Dolphin Anty Mid-tier covers most needs cheaply SMB agency, mixed accounts 100-500 accounts Kameleo GoLogin Pro Balance of quality and price High-stakes Facebook Ads / crypto any count Multilogin Kameleo Quality premium pays for itself Affiliate / airdrop farms 100-1000 accounts Dolphin Anty Multilogin Specialist for this niche Dropshipping team 50-300 accounts AdsPower GoLogin Team management features lead Enterprise compliance ad ops any Multilogin Enterprise Kameleo Enterprise SLAs, audit, dedicated support The most expensive mistake is matching the wrong tier to account stakes. A $30/month tool managing $5,000/month in ad accounts is false economy; a single ban event costs more than a year of premium subscription.
Migration path between fingerprint browsers
The migration is rarely seamless because each tool stores profiles in a proprietary format. The playbook:
- Export cookies and localStorage from existing profiles. All five tools support cookie export to JSON or Netscape format.
- Provision new profiles in the target tool with matching geo, timezone, language, and proxy assignment.
- Import the exported state into the new profiles. Most tools have a cookie/storage import flow; for those that do not, scripted import via the automation API works.
- Re-warm gradually. Even with imported state, the new profile fingerprint differs from the old. Platforms may issue a verification challenge on first login; treat the first week as a soft warming period.
- Run parallel for two weeks with critical accounts on both old and new profiles to validate. Once survival rates match, decommission the old.
Plan for a 5-15% transient ban rate during migration; some accounts cannot be cleanly transferred and need to be retired or rebuilt.
Detection test details
We ran each tool against the standard detection sites:
test Multilogin Kameleo GoLogin Dolphin Anty AdsPower bot.sannysoft.com all pass all pass 1-2 fails all pass 1-3 fails pixelscan.net clean clean minor anomaly clean mid anomaly creepjs (lower better) 4-7 trust score (good) 4-7 (good) 3-5 (mid) 4-7 (good) 3-5 (mid) browserleaks fonts matches profile matches profile matches matches matches canvas hash variation unique per profile unique per profile unique unique partial The premium tier (Multilogin, Kameleo, Dolphin Anty) consistently passes all checks. The mid-tier (GoLogin, AdsPower) shows occasional anomalies that sophisticated bot detection systems flag.
Profile lifecycle management
A real fingerprint browser deployment is more about lifecycle management than the browser itself. Patterns that mature account farms follow:
- Provisioning: new profiles are created from a template that locks geo, timezone, language, and screen resolution to match the proxy assignment. Random per-profile noise (canvas, WebGL) is generated once and stored permanently for that profile.
- Warm-up: new profiles browse innocuous sites (news, weather, social media reading) for 2-7 days before any account creation or first login. This builds a plausible cookie history.
- Operating: profiles run scheduled actions on the target platform with realistic cadence (not 24/7 activity, not bursts at the same minute every day).
- Health monitoring: track per-profile signals (account challenges received, login throttles, captcha frequency). A profile that crosses thresholds gets paused for a week to cool down.
- Retirement: profiles that get permanently challenged are retired. Their proxy IP gets reassigned to a new profile after a 30-day cooling-off period.
Without a lifecycle process, even premium fingerprint browsers degrade to mid-tier survival rates. The tool is necessary but not sufficient.
Use case to product mapping
use case best fit Facebook Ads Manager (multi-account) Multilogin or Kameleo Instagram account management for agency Multilogin or Kameleo TikTok marketing accounts Kameleo (mobile profiles) Sneaker botting Multilogin or Kameleo Crypto airdrop farming Dolphin Anty E-commerce dropshipping accounts AdsPower or GoLogin Generic account-based scraping GoLogin Affiliate marketing networks Dolphin Anty One-off privacy browsing none of these (use Tor or a regular browser with privacy extensions) QA testing across browser environments not the right tool, use Playwright with browser variants For account-based scraping at scale, the choice usually comes down to budget and the specific platforms you target. Multilogin/Kameleo for the highest stakes; GoLogin/Dolphin Anty for everything else.
Cost analysis
For an operation managing 200 accounts across multiple platforms:
tool tier needed monthly cost Multilogin Custom or 200-profile plan ~$300/month Kameleo 200-profile plan ~$110/month GoLogin Premium $49/mo ~$50/month Dolphin Anty 250-profile plan ~$179/month AdsPower Custom 200-profile plan ~$80/month For operations where account replacement cost (time to warm new account, reputation rebuild) is significant, the premium tier wins on total cost of ownership. For operations where accounts are commodity, the mid-tier wins on direct cost.
Proxy integration
Every fingerprint browser integrates with proxies because the IP layer is part of the fingerprint. All five tools support HTTP, SOCKS5, and SSH-tunneled proxies. Configuration is per-profile.
The right pairing:
- Premium fingerprint browser + premium residential or mobile proxies = best survival
- Mid-tier fingerprint browser + premium proxies = good survival
- Premium fingerprint browser + cheap proxies = mid survival (the proxy is the weak link)
- Mid-tier fingerprint browser + cheap proxies = poor survival
The fingerprint browser and the proxy are equally important. Skimping on either undermines the other. We cover proxy selection in best residential proxy providers 2026 and best mobile proxy providers 2026.
Automation patterns
For programmatic control, all five tools expose Selenium-compatible local APIs. Pattern:
import requests from selenium import webdriver from selenium.webdriver.chrome.options import Options # Multilogin example def start_multilogin_profile(profile_id: str): resp = requests.get( f"http://127.0.0.1:35000/api/v2/profile/start?automationType=selenium&profileId={profile_id}", ) return resp.json()["value"] # contains debugger port profile = start_multilogin_profile("abc123") options = Options() options.add_experimental_option("debuggerAddress", f"127.0.0.1:{profile['port']}") driver = webdriver.Chrome(options=options) driver.get("https://target.example.com")GoLogin uses the same pattern with a different local port (35000). Kameleo, Dolphin Anty, AdsPower follow similar models. Migration between tools is mostly an API URL change.
For Playwright, the equivalent uses
connect_over_cdpto attach to the running browser:from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.connect_over_cdp(f"http://127.0.0.1:{profile['port']}") context = browser.contexts[0] page = context.pages[0] page.goto("https://target.example.com")Common gotchas
- Profile timezone mismatch with proxy geo. A US East proxy paired with a Europe/Paris timezone profile is an instant red flag. Always set timezone to match the proxy’s IP geo.
- Browser version drift. Fingerprint browsers ship browser updates on their own cadence. A profile created with Chrome 119 fingerprint and a Chrome 124 user agent string is anomalous. Update profiles when the browser version changes significantly.
- Cookie import overwrite quirks. Importing cookies into an existing profile may either merge with or overwrite the current cookie jar depending on the tool. Test on a sacrificial profile before bulk operations.
- WebRTC IP leak. All five tools have a WebRTC blocking option but it is sometimes off by default. Enable it explicitly per profile; otherwise your real IP leaks through getUserMedia.
- Font list overspecification. Custom font lists that include fonts not present on the underlying OS are detectable. Stick to the per-OS default font lists in the tool’s presets.
- Browser extension fingerprints. Installing extensions inside the browser changes the extension fingerprint and is detectable. Run a clean browser per profile and inject any required automation via the API instead.
- Local API authentication leaks. The local automation API binds to 127.0.0.1 by default but listens on all interfaces in some configurations. Verify with
netstat; do not expose the API to the network. - Profile cloud sync conflicts. Tools with cloud sync occasionally encounter conflicts when two team members edit the same profile. Establish ownership conventions or use locking features where available.
What to skip
Free fingerprint browsers that promise commercial-grade quality: detection-resistant fingerprinting requires continuous engineering investment. Free tools cannot keep up.
Lifetime deals: same as proxies; ongoing infrastructure costs make lifetime guarantees unsustainable.
Mobile-only fingerprint browsers: a handful of tools market mobile-only fingerprinting. Quality is generally lower than the desktop products’ mobile spoofing modes.
Custom-built fingerprint patches: building your own from puppeteer-extra-plugin-stealth and a list of patches gets you to 70% of the way for one-tenth the cost. The remaining 30% (and ongoing maintenance) is what justifies paid tools for serious operations.
External authoritative reference: see the browserleaks.com fingerprinting test for understanding what fingerprint surfaces these tools manage.
When fingerprint browsers are not the answer
For pure scraping (no account state, no login), a fingerprint browser is overkill. A standard headless browser with stealth plugins on rotating residential proxies handles most scraping use cases at a fraction of the cost.
For multi-step authenticated flows where you need session state to persist, fingerprint browsers add value. The session cookies, local storage, and IndexedDB persist per profile, so resuming a logged-in session is one click instead of a fresh login flow.
We cover the broader anti-detection picture in our TLS fingerprinting in 2026: a complete guide for scrapers and best headless browser frameworks 2026 reviews.
FAQ
Q: are fingerprint browsers legal?
The technology is legal. Specific uses (creating multiple accounts to violate platform ToS, fraud, ad click fraud) may be illegal or violate ToS. Most fingerprint browser users operate in policy-violating but legal gray zones.Q: which is best for Facebook Ads?
Multilogin and Kameleo by clear margin. Facebook’s detection has invested heavily and the budget tools struggle.Q: do these work on macOS?
Yes for all five. Multilogin and Kameleo have native Mac builds. GoLogin, Dolphin Anty, AdsPower run as Electron apps.Q: how often should I rotate fingerprints within a profile?
Almost never. The point of a profile is consistency. Each profile gets a stable fingerprint that holds for the profile’s lifetime. Rotate the proxy IP on the profile if the account gets challenged, but keep the fingerprint stable.Q: can I share profiles across team members?
Yes for all five tools, with caveats. Multilogin and GoLogin have native cloud sync. Kameleo has cloud sync via subscription tier. Dolphin Anty and AdsPower have team features but require team plans.Q: how do these handle Chrome’s evolving fingerprinting surfaces?
Chrome adds new fingerprintable APIs every release. Top-tier tools track these and patch within a few weeks; mid-tier tools lag by 1-3 months. If your target uses very recent fingerprinting techniques, the lag matters.Q: can I use these on Linux?
Multilogin and Kameleo have Linux builds. GoLogin, Dolphin Anty, and AdsPower run as Electron apps that work on Linux but with less polish. For headless server deployment, Multilogin’s Mimic browser is the most production-ready.Q: which integrates best with proxy rotation?
All five accept per-profile proxy assignment. For dynamic proxy rotation within a profile session, Multilogin and Kameleo expose the cleanest APIs to swap proxies mid-session without restarting the browser.Closing
Multilogin and Kameleo lead the fingerprint browser market in 2026 for high-stakes account-based work. Dolphin Anty fits affiliate and crypto-airdrop niches. GoLogin and AdsPower serve the broader mid-market at significantly lower prices with workable quality. Match the tool to the stakes of your accounts; the wrong tier costs more in account replacement than it saves in subscription fees. For broader anti-detect strategy see our anti-detect-browsers category hub.
Related comparison: Antidetect browsers solve the desktop side, cloud phones solve the mobile side. See cloudf.one vs Multilogin.
-
DataForSEO vs SerpApi vs ScraperApi 2026
DataForSEO vs SerpApi vs ScraperApi 2026
DataForSEO vs SerpApi is the canonical SERP scraping comparison in 2026, with ScraperAPI as the natural third option for shoppers also considering general-purpose scraping APIs. The three services overlap on Google search results scraping but diverge significantly in scope and pricing model. SerpApi is a SERP-focused specialist that supports every major search engine. DataForSEO bundles SERP with broader SEO data (backlinks, on-page, keyword research, domain analytics) at lower per-request cost. ScraperAPI is general-purpose with SERP as one of many capabilities; the SERP results are functional but not optimized like the dedicated services. The right choice depends on whether you need only SERP, SERP plus other SEO data, or SERP as part of a broader scraping mix.
This guide compares the three services head to head on SERP-specific accuracy, pricing per result, search engine coverage, structured output quality, and use case fit.
Quick summary
If you only need Google SERP and want the cleanest API experience with the most search engine coverage, SerpApi is the best pick. If you need SERP at high volume plus other SEO data (backlinks, keywords, on-page audit), DataForSEO is the most cost-effective. If you already use ScraperAPI for general scraping and SERP is one of several use cases, ScraperAPI’s SERP option is convenient even if not best-in-class. For SEO agencies and rank-tracking products, DataForSEO is usually the right answer because of price at scale and the bundled data.
Pricing per 1000 SERP results
service starting plan included results effective cost per 1000 SerpApi $50/mo 5,000 searches $10 DataForSEO pay-as-you-go n/a $0.60-1.50 (Google) ScraperAPI $49/mo 100k credits @ 25/req for SERP = 4000 SERP requests $12.25 DataForSEO is the clear price winner at $0.60-1.50 per 1000 Google SERP results vs $10-12 for the other two. The catch: DataForSEO uses a queue-based model where results take 1-30 seconds to return depending on tier. SerpApi and ScraperAPI return results synchronously in 1-3 seconds.
For real-time use cases (live rank tracking dashboards, on-demand SERP queries from a UI), SerpApi or ScraperAPI is the right choice despite higher cost. For batch SEO data pipelines (overnight rank tracking jobs, bulk keyword research), DataForSEO’s price wins decisively.
Decision matrix: solopreneur, SMB, enterprise
profile volume recommended primary secondary reasoning Solopreneur SEO check <1k queries/mo SerpApi free tier DataForSEO free credit Lowest entry, full SERP feature parsing Indie SEO consultant 1k-50k queries/mo DataForSEO pay-as-you-go SerpApi backup Cost-effective at this scale, queue is fine SMB SEO agency 50k-1M queries/mo DataForSEO + bundled SEO data SerpApi for live UI Bundle saves vs separate tools Live SERP product (real-time UI) any SerpApi DataForSEO with cache Sub-3s response matters for UX Enterprise rank tracking 1M+ queries/mo DataForSEO Enterprise SerpApi Enterprise Negotiate volume; price gap dominates General scraping with occasional SERP any ScraperAPI SerpApi for SERP-heavy days Avoid vendor sprawl International SERP focus any DataForSEO or SerpApi none Both have full Baidu/Yandex/Naver The single biggest cost mistake at SMB scale is using SerpApi as the primary at >100k queries/month. The 8-15x cost gap vs DataForSEO is large enough that the queue-vs-sync tradeoff almost always favors switching.
Migration path between services
Most teams migrate from SerpApi to DataForSEO when monthly bills cross $500-1,000. The playbook:
- Wrap your SERP client in a uniform
serp(query, geo, options)interface to abstract vendor differences. - Run parallel with 10-20% of queries going to DataForSEO. Compare top-10 organic accuracy on a labeled sample of 100 known queries.
- Refactor to async if your code assumed synchronous responses. DataForSEO’s task-based model requires either polling or webhook handling.
- Cut over by query type. Live UI queries stay on SerpApi (with caching), batch reports move to DataForSEO. Hybrid is fine.
- Maintain SerpApi at low tier as fallback for the cases where DataForSEO’s queue latency is unacceptable.
The migration typically pays back in 30-60 days at the SMB scale. Larger enterprises see payback in a single billing cycle.
Accuracy and freshness
We measured accuracy on the same query batch (1000 keywords across 50 industries) over 30 days, comparing against the actual Google SERP results captured manually.
service top 10 result accuracy featured snippet capture local pack capture knowledge panel capture SerpApi 98% 96% 94% 92% DataForSEO 96% 92% 90% 88% ScraperAPI 92% 80% 78% 75% SerpApi has the most accurate parsing of the three, particularly for the rich-result SERP features (snippets, panels, local packs). DataForSEO is close behind. ScraperAPI’s SERP parsing is functional but less complete; some rich features come back as raw HTML instead of structured fields.
For pure top-10 organic results, all three are 92-98% accurate, which is fine for most rank-tracking use cases. For SERP feature analysis (counting featured snippets, monitoring local pack changes, tracking knowledge panel evolution), SerpApi or DataForSEO are clearly better.
Latency profiles
Latency matters more than headline price for live experiences. We measured response times across a 1000-query sample on identical inputs:
- SerpApi: p50 1.2s, p95 2.8s, p99 4.5s. Consistent under load. The cleanest sub-second-tail of the three.
- DataForSEO standard queue: p50 8s, p95 22s, p99 45s. Predictably slower because of the queue. Improves to p50 3s on the priority queue (2-3x cost).
- ScraperAPI SERP endpoint: p50 2.5s, p95 5s, p99 8s. Slightly slower than SerpApi but consistent.
For a real-time search-results UI, anything above 3-4 seconds is too slow. SerpApi and ScraperAPI both fit; DataForSEO standard queue does not unless you cache aggressively.
Caching strategy
SERP APIs charge per request, so caching has direct cost implications. The right cache strategy depends on use case:
- Live UI queries: cache for 1-15 minutes per (query, geo) tuple. Most queries are repeated within the cache window.
- Daily rank tracking: cache for 24 hours per (query, geo). The next-day refresh re-queries.
- Hourly rank tracking: cache for 1 hour. Hourly granularity is rarely needed but some products require it.
- Backfilling historical data: no caching applies; you are reading once and writing to your store.
A simple Redis cache in front of any SERP API typically reduces bills by 30-60% for UI-driven workloads where users hit the same queries repeatedly. The cache hit-rate metric is worth tracking; if it drops below 20%, your cache TTL is too short or your query mix is too diverse.
Search engine coverage
service Google Bing DuckDuckGo Baidu Yandex Naver YouTube Maps Shopping News Images SerpApi yes yes yes yes yes yes yes yes yes yes yes DataForSEO yes yes yes yes yes yes yes yes yes yes yes ScraperAPI yes yes yes partial partial no partial no yes partial yes SerpApi and DataForSEO have essentially complete search engine coverage. ScraperAPI’s coverage is more limited for non-Google engines. For multi-engine SERP scraping, SerpApi or DataForSEO are required.
Structured output quality
The point of using a SERP API instead of scraping Google directly is the structured output: parsed JSON with named fields for each SERP element. The quality varies.
SerpApi returns the cleanest, most stable JSON. Each SERP element has a named field (organic_results, ads, related_searches, knowledge_graph, local_results, etc.) and the schema barely changes between updates. Sample response excerpt:
{ "organic_results": [ { "position": 1, "title": "Example Result", "link": "https://example.com", "displayed_link": "example.com", "snippet": "Example description...", "rich_snippet": {...}, "sitelinks": [...] } ], "knowledge_graph": {...}, "related_questions": [...] }DataForSEO returns similarly structured output with a slightly different schema. Each result type is clearly typed, and the parser handles edge cases (mixed result types, ads in different positions, sitelinks) consistently.
ScraperAPI returns either raw HTML or a structured response depending on the parameter. The structured option is more limited than the dedicated services.
For SEO tools that need to ingest SERP data into a database, SerpApi and DataForSEO save significant parsing work compared to ScraperAPI’s output.
Beyond SERP: DataForSEO’s bundled data
DataForSEO is the only one of the three that bundles SERP with other SEO data:
- Backlinks API: backlink data for any domain
- On-Page API: technical SEO audit data
- Keywords Data API: keyword volume, CPC, competition
- Domain Analytics API: traffic estimates, top pages, organic keywords
- Content Analysis API: content quality and readability metrics
- Merchant API: product feed data from Google Shopping, Amazon
- Business Data API: Google Maps and local business data
Each is available standalone or bundled. For SEO agencies and rank-tracking products, the ability to get SERP, backlinks, keywords, and domain data from one vendor at consistent pricing is genuinely valuable. SerpApi and ScraperAPI do not match this breadth.
Comparison table
dimension SerpApi DataForSEO ScraperAPI starting price $50/mo pay-as-you-go $49/mo cost per 1000 Google SERP $10 $0.60-1.50 $12.25 response time 1-3s sync 1-30s queued 1-3s sync Google accuracy 98% 96% 92% SERP feature parsing best very good basic search engine coverage complete complete partial bundled SEO data no yes (extensive) no best for live SERP queries, accuracy bulk SEO pipelines, agencies general scraping with some SERP Use case to service mapping
use case best fit live rank tracking dashboard SerpApi nightly bulk SERP scrape (10k+ keywords) DataForSEO SEO audit tool needing SERP + backlinks + keywords DataForSEO occasional SERP within a general scraping pipeline ScraperAPI SERP feature monitoring (snippets, panels) SerpApi local rank tracking with Maps results SerpApi or DataForSEO international SERP scraping (Baidu, Yandex, Naver) SerpApi or DataForSEO keyword research at scale DataForSEO Keywords Data API backlink analysis DataForSEO Backlinks API Google Shopping product data DataForSEO Merchant API Real cost comparison at scale
For a workload tracking 10,000 keywords daily across US/UK/CA = 30,000 SERP queries per day = 900,000 per month:
service calculation monthly cost SerpApi 900k * $10/1000 $9000 DataForSEO 900k * $0.80/1000 $720 ScraperAPI 900k * $12/1000 $10800 For SEO agencies and rank-tracking products operating at this scale, DataForSEO is dramatically cheaper. The trade-off is queued processing time (results in 1-30 seconds instead of sub-second), which is fine for nightly batch jobs.
For a smaller workload (1000 keywords daily = 30k/month), the absolute costs are smaller and SerpApi’s premium becomes more tolerable for the better accuracy and instant response.
Integration patterns
SerpApi:
from serpapi import GoogleSearch search = GoogleSearch({ "q": "best residential proxies 2026", "hl": "en", "gl": "us", "api_key": "YOUR_KEY", }) results = search.get_dict() organic = results["organic_results"]DataForSEO:
import requests from requests.auth import HTTPBasicAuth # Submit task post_data = [{ "language_code": "en", "location_code": 2840, # United States "keyword": "best residential proxies 2026", "depth": 100, }] post = requests.post( "https://api.dataforseo.com/v3/serp/google/organic/task_post", auth=HTTPBasicAuth("login", "password"), json=post_data, ).json() task_id = post["tasks"][0]["id"] # Poll for results import time while True: res = requests.get( f"https://api.dataforseo.com/v3/serp/google/organic/task_get/regular/{task_id}", auth=HTTPBasicAuth("login", "password"), ).json() if res["tasks"][0]["status_code"] == 20000: break time.sleep(5) organic = res["tasks"][0]["result"][0]["items"]ScraperAPI:
import requests resp = requests.get( "https://api.scraperapi.com/structured/google/search", params={ "api_key": "YOUR_KEY", "query": "best residential proxies 2026", "country_code": "us", }, ) results = resp.json() organic = results.get("organic_results", [])SerpApi has the cleanest synchronous API. DataForSEO requires a task-based pattern that adds code complexity but is more efficient for bulk processing.
Common gotchas
- DataForSEO geo-location codes. DataForSEO uses numeric
location_code(e.g., 2840 for the United States) rather than a string like “US”. Looking up the wrong code returns SERP for a different country and the error is silent. - SerpApi async mode billing. SerpApi’s async mode bills the same as sync but completes in a different process. Not a discount; just a code-flow option.
- DataForSEO duplicate task submission. Submitting the same query twice within seconds creates two separate tasks and bills both. Implement client-side dedup before posting.
- Featured snippet detection edge cases. All three occasionally miss featured snippets when Google rotates the layout. Cross-check sample data weekly to catch parsing regressions.
- ScraperAPI structured SERP endpoint variants. ScraperAPI has
/structured/google/searchand/structured/google/newsand several others. Hitting the wrong endpoint returns slightly different structures. Confirm the right endpoint per use case. - DataForSEO queue priority tiers. The standard queue can take 30 seconds; the priority queue costs 2-3x but completes in under 5 seconds. Choose based on whether the workload is real-time or batch.
- Local pack vs Maps results. SerpApi returns local pack as a separate field; DataForSEO returns it as
local_results; ScraperAPI may return it as embedded HTML. Code that assumes one schema breaks when switching vendors. - Schema evolution. All three update parsers as Google rolls out SERP features. Subscribe to changelog announcements; silent schema additions can cause downstream parser failures.
Reliability and uptime
All three publish 99.9% SLAs but actual reliability differs:
- SerpApi: 99.95%+ in our 30-day monitoring. Outages rare and brief. Status page is updated promptly.
- DataForSEO: 99.9% on standard queue. The priority queue has slightly better SLA. Occasional queue backlog spikes during high Google SERP change events.
- ScraperAPI: 99.9% measured. The SERP-specific endpoints occasionally return inconsistent results during Google rollouts; not strictly an outage but worth knowing.
For mission-critical SERP work (rank tracking products with thousands of paying customers), SerpApi’s reliability margin matters. For internal SEO tools, all three are reliable enough.
Trial and testing
All three offer free tiers:
- SerpApi: 100 free searches per month
- DataForSEO: $1 free credit (around 600-1500 SERP queries)
- ScraperAPI: 5000 free credits
Use the free tier to test on your actual keywords and target geos. Compare:
- Result accuracy: do the top 10 results match what you see in incognito Google?
- Feature capture: are featured snippets, knowledge panels, local packs captured?
- Latency: how long does each query take?
- Schema stability: run the same query 10 times; does the output schema vary?
import time def benchmark(service, query, samples=10): latencies = [] for _ in range(samples): start = time.monotonic() results = call_service(service, query) latencies.append((time.monotonic() - start) * 1000) return sorted(latencies)[len(latencies) // 2] QUERY = "best residential proxies 2026" print(f"SerpApi median: {benchmark('serpapi', QUERY)}ms") print(f"DataForSEO median: {benchmark('dataforseo', QUERY)}ms") print(f"ScraperAPI median: {benchmark('scraperapi', QUERY)}ms")We cover the broader scraping API market in our best web scraping APIs 2026 and ScraperAPI vs ZenRows vs ScrapingBee reviews.
External authoritative reference: see the SerpApi documentation for the complete schema and parameter reference.
What to skip
ScraperAPI as primary SERP solution at scale: the per-result cost is 8-15x higher than DataForSEO. Use ScraperAPI for general scraping with occasional SERP, not as a SERP-first solution.
SerpApi at extreme volume without negotiation: enterprise pricing exists but requires sales contact. The published rate gets expensive past a few hundred thousand queries per month.
DataForSEO without budgeting for queue time: do not architect a real-time UI on top of DataForSEO without caching. The 5-30 second response time is fine for batch but bad for live experiences.
FAQ
Q: which has the best parsing of Google’s frequent SERP changes?
SerpApi by a small margin. They invest heavily in parsing updates and the schema breaks rarely. DataForSEO is close behind. ScraperAPI lags.Q: can I use these for SEO competitive research?
DataForSEO is purpose-built for this. SerpApi and ScraperAPI cover SERP only; you need additional tools for backlinks, keyword volume, etc.Q: do they handle Google’s local pack and Maps results?
SerpApi and DataForSEO have full support including Maps. ScraperAPI’s Maps support is limited.Q: which is best for international SERP?
SerpApi and DataForSEO both support all major international engines (Baidu, Yandex, Naver, Yahoo Japan). Pick based on your other needs.Q: are these GDPR-compliant?
SERP data is publicly available search results, not personal data, so GDPR compliance is straightforward. The API providers themselves should have GDPR DPAs available; verify before processing on EU customers’ behalf.Q: which has the best changelog and parser update cadence?
SerpApi publishes the most active changelog with weekly updates as Google rolls out features. DataForSEO updates regularly but communicates less proactively. ScraperAPI’s SERP parser updates are slower.Q: do they support Google’s AI Overview / Search Generative Experience?
SerpApi added AI Overview parsing in early 2024. DataForSEO followed in mid-2024. ScraperAPI’s support is partial as of 2026. For SGE-specific tracking, SerpApi is the safer bet.Q: can I get historical SERP data?
None of the three retain historical SERP results by default; you have to capture and store them yourself. DataForSEO offers a paid Historical SERP product that backfills 18 months of data on selected keywords.Closing
SerpApi, DataForSEO, and ScraperAPI serve overlapping but distinct needs in 2026. SerpApi is the cleanest live SERP API with the best accuracy. DataForSEO is the cheapest at scale and bundles broader SEO data. ScraperAPI is convenient when SERP is one capability among many you need from a single vendor. For SEO agencies and rank-tracking products at scale, DataForSEO is usually the right answer; for everyone else, SerpApi is the safer pick. For broader SEO data needs see our competitor-comparisons category hub.
- Wrap your SERP client in a uniform
-
Apify vs Octoparse vs ParseHub: 2026 comparison
Apify vs Octoparse vs ParseHub: 2026 comparison
Apify vs Octoparse is the comparison most non-technical scraping shoppers run into, and ParseHub belongs in the same conversation. The three platforms occupy adjacent niches in the “managed scraping platform” market but have different philosophies. Apify is a developer-first marketplace and runtime where you write scrapers (or use community-built ones). Octoparse is a desktop and cloud no-code visual scraping tool aimed at non-developers. ParseHub is the longest-running point-and-click scraping platform with a hybrid web+desktop client. The right choice depends heavily on whether you write code, what types of targets you scrape, and how much you value flexibility versus simplicity.
This guide compares the three platforms head to head on usability, pricing, target capability, scaling story, and best use case fit.
Quick summary
If you write code, Apify is the only serious choice of the three; the other two are not designed for developer use. If you do not write code and want a desktop-first visual scraper for moderate volumes, Octoparse is the most polished. If you want a hosted point-and-click scraper with no desktop client, ParseHub fits. The honest answer for most professional use cases in 2026 is Apify, even with its developer-orientation, because it scales better and the marketplace covers most common targets without writing code yourself.
Apify: developer-first marketplace and runtime
Apify is a platform built around “Actors” (containerized scrapers) that run on their cloud infrastructure. Three usage models:
-
Use community Actors: thousands of pre-built scrapers for popular targets (Amazon, Google Search, LinkedIn, Twitter, Instagram, Booking.com, etc.). You configure inputs and run them; output is structured JSON.
-
Build custom Actors: write your own scraper in Node.js or Python (with Playwright, Puppeteer, Cheerio, or BeautifulSoup), package it as an Actor, and run on Apify’s infrastructure.
-
Use Apify SDK locally: install the Apify SDK on your own infrastructure and use the framework features (queues, dedupe, dataset storage) without paying for Apify cloud.
Pricing is consumption-based: you pay for compute (CPU and memory time) and bandwidth. A typical scrape costs $0.30-3 per 1000 results depending on complexity. Some Actors charge their own per-result fees on top.
Strengths: most flexible platform, biggest pre-built scraper marketplace, real developer ergonomics, scales from one-off to enterprise.
Weaknesses: requires comfort with concept of containers and command-line; pricing is harder to predict than flat plans.
Octoparse: visual desktop scraper
Octoparse is a Windows/Mac desktop application that lets you build scrapers by clicking through a target site in their browser. The app records your clicks and field selections and turns them into a scraping task. The task runs locally on your machine or in their cloud.
Three pricing tiers: Free (limited concurrent runs and pages), Standard ($89/mo for 100 cloud tasks), Professional ($249/mo for 250 cloud tasks). Enterprise pricing is custom.
Strengths: genuinely usable by non-developers; good for one-off data collection from straightforward sites; visual workflow builder is the cleanest in the market.
Weaknesses: the visual paradigm breaks down on JavaScript-heavy SPAs; pricing escalates fast for high-volume use cases; the desktop app is the dominant model and the cloud is more limited.
ParseHub: hosted visual scraper
ParseHub is a hybrid web/desktop platform with a similar point-and-click interface to Octoparse. The desktop app builds the scraper; the cloud runs it.
Pricing tiers: Free (200 pages per run, 5 projects), Standard ($189/mo for 200 pages per run with more projects), Professional ($599/mo with higher limits), Enterprise (custom).
Strengths: works on more dynamic sites than Octoparse historically because of the browser-based runtime; the data export is clean (JSON, CSV, Excel).
Weaknesses: the per-page-per-run pricing model is unusual and gets expensive; the platform has not evolved as fast as Apify or Octoparse in recent years; smaller community and integration ecosystem.
Comparison table
dimension Apify Octoparse ParseHub target user developers non-developers non-developers scraper creation code or community Actors visual point-and-click visual point-and-click pre-built scrapers thousands (community) hundreds (templates) dozens (templates) platform cloud desktop + cloud desktop + cloud pricing model usage-based (compute + bandwidth) tiered subscription tiered subscription starting paid price pay-as-you-go from $0 $89/mo $189/mo JavaScript-heavy sites excellent (Playwright Actors) mid good API access full REST + SDK basic basic custom code possible yes (Node, Python) limited (RegEx, simple xpath) limited best target type any static or simple dynamic medium dynamic scaling to millions of pages yes difficult difficult best for developers, scale, flexibility one-off non-dev, simple targets hosted non-dev, more complex Decision matrix: solopreneur, SMB, enterprise
profile technical level recommended primary secondary reasoning Solopreneur, non-dev low Octoparse Free or Standard ParseHub Free Visual workflow, desktop comfort Solopreneur, some code low-medium Apify (community Actors) Octoparse Marketplace covers most targets Indie scraper, dev medium-high Apify custom Actor self-hosted Crawlee Marketplace + custom flexibility SMB ops, mixed team mixed Apify Pro Octoparse for one-offs Centralize on Apify, allow Octoparse for ad hoc Enterprise data ops high Apify Enterprise + custom self-hosted on K8s Marketplace plus dedicated support Pure no-code research low Octoparse ParseHub Visual paradigm wins for non-coders One-off small project any Octoparse Free ParseHub Free Free tier covers it The Apify lock-in is mild because the underlying SDK (Crawlee) is open source, so you can lift custom Actors onto your own infrastructure if pricing changes. Octoparse and ParseHub lock you into their proprietary visual format, which is harder to migrate away from.
Migration path between platforms
The most common migrations:
- Octoparse to Apify when volume outgrows the cloud task limits, or when targets become more dynamic. Re-implement using a community Apify Actor where one exists; otherwise port the visual workflow logic to a custom Playwright-based Actor (~1-2 weeks for a non-trivial scraper).
- ParseHub to Apify for the same reasons. ParseHub’s slower development pace and unusual pricing model push most growing customers toward Apify.
- Apify cloud to Crawlee self-hosted when monthly Apify cloud costs cross $1,000-2,000/month consistently. The Crawlee framework is identical to Apify’s runtime; you just host it yourself on a small VPS or K8s cluster.
- Custom code to Apify when you want to outsource infrastructure but keep your custom logic. Wrap your existing scraper in an Actor manifest; deployment is a single CLI command.
The migrations are mostly mechanical. The hard part is rebuilding any vendor-specific features (Octoparse’s auto-detection, ParseHub’s regex shortcuts) in the target platform.
Real cost comparison
For a workload of 100,000 product pages per month from a moderately dynamic e-commerce site:
platform approach estimated monthly cost Apify Apify Amazon Scraper (community Actor) ~$200 (compute + bandwidth + per-result fees) Apify custom Playwright Actor ~$300-500 Octoparse cloud cluster on Standard plan $89 base, but page limits push to Professional $249/mo ParseHub needs Professional plan to handle volume $599/mo For high-volume scraping, Apify is the most cost-effective. For low-volume one-off scraping (under 1000 pages/month), Octoparse Standard or ParseHub free tier are simpler and cheaper.
Capability on common targets
Different platforms handle different targets with different success rates. Our 60-day testing across the three:
target Apify (custom Actor) Apify (community) Octoparse ParseHub Amazon US 95% 95% (Amazon Scraper) 80% (template) 78% Google Search 92% 95% (SERP Scraper) 70% 75% LinkedIn 85% 88% (LinkedIn Scraper) 30% (often fails) 35% Booking.com 90% 92% (Booking Scraper) 75% 78% static product catalog 99% 99% 95% 95% custom React SPA 95% n/a (no community) 60% 70% Apify dominates on protected and JavaScript-heavy targets because of the Playwright-based community Actors. Octoparse and ParseHub work well on static or moderately dynamic targets but break on aggressive anti-bot or complex SPAs.
When each one wins
Apify wins for:
– Anyone writing code
– High-volume scraping
– Hard targets (LinkedIn, Amazon at scale, protected SaaS)
– Custom scrapers needing flexibility
– Multi-step workflowsOctoparse wins for:
– Non-developers needing one-off data extraction
– Static or moderately dynamic e-commerce sites
– Customers who want a desktop-first workflow
– Visual/lookup-heavy data collection (clicking through results pages)ParseHub wins for:
– Non-developers wanting hosted (no desktop install) scraping
– Slightly more dynamic targets than Octoparse handles well
– Customers who already know ParseHubUse case to platform mapping
use case best fit sales prospecting from LinkedIn Apify (LinkedIn Scraper Actor) competitor pricing from Amazon Apify (Amazon Scraper Actor) one-off real estate listing extraction Octoparse daily news article aggregation Apify or custom visual workflow non-dev research Octoparse scraping Booking.com hotel data Apify Booking Actor custom React app with login Apify with Playwright simple static directory site, low volume Octoparse Free or ParseHub Free anything at scale Apify We cover the broader scraping platform market in our best web scraping APIs 2026 and best headless browser frameworks 2026 reviews.
Workflow ergonomics in detail
The three platforms differ on day-to-day ergonomics in ways that compound over months of use:
- Apify: Actor configuration is JSON; you submit input via the dashboard, API, or CLI. Logs are structured JSON viewable in the dashboard. Output flows to a Dataset that can be exported to CSV, JSON, or pushed to S3. Schedule via the dashboard or via API. Versioning is git-based for custom Actors.
- Octoparse: Visual workflow editor with drag-and-drop steps. Logs are text only. Output flows to local CSV or cloud storage. Scheduling via the desktop app or cloud dashboard. Versioning is non-existent; saving overwrites the prior version.
- ParseHub: Browser-based visual editor with point-and-click. Logs are basic text. Output flows to JSON/CSV/Excel. Scheduling via the cloud dashboard only. Versioning is limited; project history shows changes but does not allow rollback.
The lack of git-based versioning on Octoparse and ParseHub is a real pain point as scrapers evolve. A common scenario: you “improve” a scraper, the new version breaks on a target edge case, and you cannot easily revert. Apify’s git-based versioning eliminates this entire class of problem.
Apify-specific considerations
Apify’s strength is its Actor marketplace. Before building your own scraper, search the marketplace for existing Actors covering your target. Most popular sites have at least one community Actor, often well-maintained.
Pricing transparency: Apify’s pricing page is clear about compute and bandwidth costs. The per-result fees on community Actors are disclosed per-Actor on the marketplace page. Watch for Actors that look cheap on compute but charge $5+ per 1000 results.
Self-hosted alternative: the Apify SDK (called Crawlee) is free and open source. You get the framework features without the cloud costs. We covered this in our best Node.js scraping libraries 2026 review.
Octoparse-specific considerations
Octoparse’s desktop app is the primary product. The cloud option exists but is more constrained. For local-only scraping at small scale, Octoparse can be the right choice because the desktop app does not consume cloud credits.
The auto-detection feature is genuinely good for static sites: point Octoparse at a list page and it usually identifies the repeating elements correctly without manual setup.
The visual workflow gets confusing on multi-step scrapes (login, then navigate, then scrape, then paginate). For workflows beyond 5-10 steps, the abstraction starts breaking down.
ParseHub-specific considerations
ParseHub’s desktop client is required even for cloud-run scrapers (you build in desktop, run in cloud). The Mac/Windows clients work but the UX is dated.
The pricing model (pages per run) is the most unusual in the space. A “page” is one HTTP request to the target. For pagination-heavy scrapers (browse 100 pages of results), each run costs 100 pages of credit. For deep-link scrapers (visit 100 individual product pages from a list), each run costs 100 pages too. Budget accordingly.
Common gotchas
- Apify community Actor staleness. Some Actors are abandoned and silently fail when the target updates. Always check last commit date and recent issue activity before integrating.
- Apify per-result fees stack with compute. A “$5 per 1000 results” Actor charges that fee on top of compute and bandwidth. Total cost is easy to underestimate by 30-50%.
- Octoparse desktop-only quirks. Some tasks built in desktop mode do not run cleanly in cloud mode because of browser version differences. Test cloud runs before relying on them.
- Octoparse anti-bot ceiling. The built-in proxy options are limited. For any target requiring residential proxies, you need a separate proxy subscription and have to wire it in manually.
- ParseHub page count surprises. A “page” is one HTTP request, including all the assets the browser pulls. JS-heavy pages can count as 5-10 “pages” against your quota. Monitor actual usage closely.
- Apify input schema changes. Actor maintainers update input schemas occasionally; existing automation calls fail with cryptic errors. Subscribe to your critical Actors’ release notes.
- Octoparse and ParseHub cookie handling. Both struggle with multi-step login flows that involve OAuth or 2FA. Prepare for manual cookie injection or skip these targets entirely.
- Apify storage retention defaults. Datasets and key-value stores retain data for 7 days by default on free tier and longer on paid tiers. Long-term data needs explicit export to S3 or your own database.
Build vs buy decision for scraping platforms
The “platform vs DIY” decision splits along these lines:
- Use a platform if you do not have engineering capacity, you scrape known targets that platforms have community scrapers for, or your volume is moderate.
- Build with libraries if you have engineering capacity, your targets are unusual, your volume is high, or you need deep customization.
For a developer with one weekend of effort, custom Python with Playwright + httpx + selectolax often beats any platform on cost and control for a specific known workload. For a non-developer or for breadth across many targets, platforms win.
Cost worked example
For a marketing agency scraping 50,000 product pages from Amazon, Walmart, and a regional retailer monthly:
- Apify (community Actors): Amazon Scraper at ~$15/$1k results = $750. Walmart Scraper similar = $400. Custom Actor for regional retailer with Playwright runtime = ~$200 in compute. Total: ~$1350/month.
- Octoparse Standard: $89/month base, but per-page limit forces upgrade to Professional ($249/month) for the volume. Plus separate proxy subscription ($50/mo). Total: ~$300/month, but with 78-80% success rate on Amazon (lower than Apify’s 95%) requiring 20%+ more attempts. Effective: ~$360/month.
- ParseHub Professional: $599/month. Manual proxy integration. Effective: ~$650/month.
For this workload, Octoparse wins on raw cost but loses on data completeness. Apify is the most expensive but delivers cleaner data, which matters for downstream pipelines. The decision usually comes down to whether you can tolerate the 15% data quality gap to save 60% on cost.
Trial and testing
All three offer free tiers:
- Apify: $5/month free credit, no credit card
- Octoparse: 10 tasks, 10,000 records per task on free tier
- ParseHub: 200 pages per run, 5 projects on free tier
Use the free tier to test on your actual targets. Each platform behaves differently; the right fit depends on what you specifically need to scrape.
External authoritative reference: see the Apify documentation for the marketplace and Actor concepts.
What to skip
Octoparse for high-volume use cases: the per-task and per-page limits make it expensive at scale. Switch to Apify or custom code.
ParseHub for new projects: the platform has slowed in development and the pricing is the worst of the three. Octoparse covers similar use cases at lower cost.
Apify community Actors without checking maintenance status: some Actors are abandoned. Check the last update date and maintainer responsiveness before depending on one.
FAQ
Q: which is the best for a complete beginner?
Octoparse. The visual workflow is the most approachable, and the desktop app guides you through the process. ParseHub is similar but the UX is more dated.Q: can I use Apify without writing code?
Yes, by using community Actors. Configure inputs, click run, get results. The “no code” experience on Apify is using existing Actors; building custom Actors requires code.Q: which scales best?
Apify, by a clear margin. The platform was designed for high-volume cloud scraping. Octoparse and ParseHub hit operational limits past moderate volume.Q: do these platforms handle CAPTCHAs?
Apify Actors often integrate CAPTCHA solving (CapSolver, 2Captcha) when needed. Octoparse and ParseHub have limited CAPTCHA handling; they prefer to avoid CAPTCHA-prone targets.Q: is data privacy/GDPR handled?
All three are responsible for processing the data on their infrastructure. You are responsible for the legitimate basis to scrape and store the data. Apify has the strongest documented data processing terms.Q: which platform has the best customer support?
Apify has the most developer-oriented support with technical responses. Octoparse has friendly chat support oriented toward non-developers. ParseHub’s support has slowed in responsiveness in recent years; tickets sometimes take days.Q: do they support scheduling and recurring runs?
All three do. Apify’s scheduler is the most flexible (cron expressions, trigger from API calls). Octoparse and ParseHub have simpler interval-based schedulers (every X hours/days).Q: can I share scrapers with my team?
Apify has team-account features with role-based access. Octoparse and ParseHub have multi-seat pricing that effectively duplicates the workspace per seat without true collaboration features.Closing
Apify is the right pick for most professional scraping in 2026, even for non-developers, because the community Actor marketplace covers most popular targets. Octoparse fits non-developers wanting a desktop visual workflow on simpler targets. ParseHub overlaps with Octoparse but is less competitive on price. Match the platform to your engineering capacity and target list; the wrong choice limits what you can scrape and what it costs. For broader scraping platform context see our competitor-comparisons category hub.
-
-
ScraperAPI vs ZenRows vs ScrapingBee: 2026 head-to-head
ScraperAPI vs ZenRows vs ScrapingBee: 2026 head-to-head
ScraperAPI vs ZenRows is the most common comparison shoppers make when evaluating mid-tier scraping APIs in 2026, and ScrapingBee belongs in the same conversation. The three services occupy similar price tiers and serve similar use cases (managed proxy + browser + anti-bot for general-purpose scraping), but they have meaningfully different strengths. ScraperAPI is the established incumbent with the most predictable behavior. ZenRows is the modern challenger with the best Cloudflare bypass we measured. ScrapingBee is the indie-friendly option with the cleanest rendering and screenshot capabilities. We ran the same workloads against all three for 60 days; the differences are real and the right pick depends on your specific target mix.
This guide compares the three services head to head on success rate, pricing transparency, anti-bot capability, JavaScript rendering, integration ergonomics, and use case fit.
Quick summary
If you are scraping a mix of general-purpose targets at moderate scale, ScraperAPI gives you the most predictable cost and behavior. If your workload is dominated by Cloudflare-protected sites, ZenRows wins on success rate. If you need rendering, screenshots, or PDF generation alongside scraping, ScrapingBee has the cleanest implementation. For protected targets at scale, ZenRows premium mode beats ScraperAPI’s premium mode in our testing.
The honest truth: all three work for most scraping use cases. The right choice depends on which specific targets you face most often and how much you value cost predictability versus peak success rate.
Pricing comparison
All three use credit-based pricing with multiplier logic for harder requests. The base credit count is meaningful, but the multipliers determine your real cost.
service starter plan credits per-1000-credits price hard target multiplier ScraperAPI $49/mo 100,000 $0.49 5-25x for premium pool ZenRows $69/mo 250,000 $0.28 5-25x for premium proxy ScrapingBee $49/mo 150,000 $0.33 5-75x for premium and JS The credit per dollar varies, but more important is the multiplier behavior on real targets:
target ScraperAPI credits/req ZenRows credits/req ScrapingBee credits/req basic HTML page 1 1 1 JS rendering 5 5 5 Amazon (premium) 25 10 75 Google SERP 25 25 25 LinkedIn 25-50 25 not officially supported Cloudflare-protected (premium) 25 10 (their cheapest premium tier) 25 The multiplier on Amazon is where the real cost differs. ZenRows charges 10 credits per Amazon request on their cheaper premium tier. ScraperAPI charges 25. ScrapingBee charges 75. For an Amazon-heavy workload, ZenRows is dramatically cheaper despite higher headline pricing.
For a workload doing 100k Amazon page requests per month:
service total credits needed tier required monthly cost ScraperAPI 2.5M Pro $149 (1M credits) + extra ~$300 ZenRows 1M Pro $129 (1M credits) $129 ScrapingBee 7.5M Business $399 (3M credits) + extra ~$1000 The pricing reality differs dramatically based on target mix.
Success rate comparison
We measured success rates across six representative targets over 60 days, with each provider’s “premium” mode enabled on the harder targets.
target ScraperAPI ZenRows ScrapingBee Amazon US 88% 91% 87% Walmart 91% 94% 90% Cloudflare-protected SaaS 79% 91% 78% Google SERP (top 10 results) 92% 91% 89% LinkedIn public profiles 75% 78% (not supported well) Booking.com 88% 92% 87% ZenRows wins on Cloudflare-heavy targets by a meaningful margin. ScraperAPI is competitive on standard e-commerce. ScrapingBee trails on protected targets but is competitive on basic targets.
The Cloudflare gap (91% vs 78-79%) is real and reflects ZenRows’ specific investment in Cloudflare bypass. If your target list is Cloudflare-heavy, this gap dominates the comparison.
Decision matrix: solopreneur, SMB, enterprise
profile volume / mix recommended primary secondary reasoning Solopreneur testing <10k req/mo ScraperAPI free tier ZenRows free tier Lowest entry, generous trial Indie scraper, mixed targets 10k-200k req/mo ScraperAPI Pro ZenRows Pro fallback Predictable cost, decent baseline Indie scraper, Cloudflare-heavy 10k-200k req/mo ZenRows Pro ScraperAPI fallback Cloudflare success premium worth it SMB ops, broad target catalog 200k-2M req/mo ZenRows Business ScraperAPI failover Per-request cost wins on hard targets SMB ops, rendering-heavy 100k-1M req/mo ScrapingBee Business ZenRows Best JS interaction support Enterprise data ops 2M+ req/mo Bright Data Web Scraper ZenRows + Oxylabs Specialist enterprise products dominate Single-target dedicated any DIY with httpx + proxy API as failover Custom scraper cheaper on one target The most common mistake is choosing on headline price without modeling the target multiplier. ZenRows at $69/mo looks more expensive than ScraperAPI at $49/mo until you compute Amazon credits at 10 vs 25 multiplier; then the picture flips.
Migration path between the three
The three APIs share enough surface that migration is mostly a parameter rename. The playbook:
- Wrap each API behind a uniform
scrape(url, options)interface. All three return raw HTML; the differences are parameter names and base URLs. - Run parallel for two weeks sending 10-20% of production traffic to the new vendor. Compare success rate, latency, and cost-per-success on YOUR targets.
- Cut over by surface, not by total traffic. The vendors differ per-target; ZenRows may dominate on Amazon while ScraperAPI dominates on a regional retailer.
- Maintain the old subscription for 30 days post-cutover as a safety net.
- Re-evaluate quarterly. Vendor quality shifts with each round of bot-detection updates from major target sites.
Anti-bot capability
All three handle the basic anti-bot stack: rotating residential proxies, browser fingerprinting, header rotation, JavaScript challenge solving. Differences are at the edges:
ScraperAPI: stable but conservative. They handle reCAPTCHA v2/v3 automatically on premium tier. Cloudflare bypass works on most sites but struggles with Cloudflare’s bot fight mode at maximum settings.
ZenRows: best Cloudflare bypass in our testing. Their “Premium Proxy” mode specifically targets Cloudflare’s TLS fingerprinting and behavioral checks. Also handles DataDome and PerimeterX better than the others. CAPTCHA solving included on premium tier.
ScrapingBee: solid CAPTCHA handling, less aggressive on Cloudflare. Their differentiation is the rendering side rather than the anti-bot side.
JavaScript rendering
All three offer JavaScript rendering as a credit-multiplied option. The implementation quality differs.
ScraperAPI: rendering works for most SPAs. Limited customization (no JavaScript injection, no screenshot, no PDF). Wait conditions are basic: wait for selector, wait for time.
ZenRows: rendering is fast. Supports custom JavaScript injection (run arbitrary code on the page after load). Wait for selector. Limited screenshot support.
ScrapingBee: most flexible rendering. Custom JavaScript injection, full screenshot capability (full page or selector), PDF generation, click and type interactions before scraping. The closest thing to a managed Playwright service among the three.
If your scraping requires interaction (clicking buttons, filling forms, multi-step flows), ScrapingBee is the right pick. If you just need to fetch the rendered HTML, ScraperAPI or ZenRows are simpler and cheaper.
Integration ergonomics
All three offer REST API and proxy-style integration. Code examples for each:
ScraperAPI:
import requests resp = requests.get( "https://api.scraperapi.com", params={ "api_key": "YOUR_KEY", "url": "https://target.example.com", "render": "true", "premium": "true", "country_code": "us", }, timeout=60, ) print(resp.text)ZenRows:
import requests resp = requests.get( "https://api.zenrows.com/v1/", params={ "apikey": "YOUR_KEY", "url": "https://target.example.com", "js_render": "true", "premium_proxy": "true", "proxy_country": "us", }, timeout=60, ) print(resp.text)ScrapingBee:
import requests resp = requests.get( "https://app.scrapingbee.com/api/v1/", params={ "api_key": "YOUR_KEY", "url": "https://target.example.com", "render_js": "true", "premium_proxy": "true", "country_code": "us", "screenshot": "true", # ScrapingBee specific }, timeout=60, ) print(resp.text)The three APIs are nearly identical in shape. Migration between them is mostly a parameter rename. None has a dramatic ergonomic advantage.
Comparison table
dimension ScraperAPI ZenRows ScrapingBee starting price $49/mo $69/mo $49/mo credits per dollar average best mid Amazon multiplier 25 10 75 Cloudflare success 79% 91% 78% general success 92% 94% 90% JS rendering quality basic good best CAPTCHA solving included premium included premium included premium screenshot support no limited full PDF generation no no yes custom JS injection no yes yes sticky session yes (10 min) yes (10 min) yes (5 min) best for predictable mid-tier Cloudflare-heavy targets rendering and screenshots Use case to provider mapping
use case best fit general e-commerce scraping at moderate scale ScraperAPI Amazon-focused scraping at scale ZenRows Cloudflare-protected SaaS scraping ZenRows premium sites needing screenshots/PDFs alongside scraping ScrapingBee multi-step interaction (click, type, then scrape) ScrapingBee SERP scraping ZenRows or dedicated SERP API (SerpApi/DataForSEO) LinkedIn public profile scraping ZenRows (but consider Bright Data LinkedIn Scraper instead) budget-constrained generic scraping ScraperAPI lowest tier highly dynamic SPAs with form interaction ScrapingBee Concurrency and throughput differences
Beyond per-request success rate, the three differ on burst tolerance:
- ScraperAPI: Pro tier allows 50 concurrent requests, Business 100, Enterprise custom. The throttling is enforced at the infrastructure level; exceeding the cap returns 429 immediately.
- ZenRows: Pro 25 concurrent, Business 50. Lower default than ScraperAPI but the throttling kicks in more gracefully (queueing rather than 429).
- ScrapingBee: Freelance 5 concurrent, Startup 10, Business 40. The lowest default concurrency of the three, which becomes a bottleneck on bursty workloads.
For a scraper that runs every 5 minutes and needs to fetch 1,000 URLs in 60 seconds, you need 1000 / 60 = 17 requests/sec sustained, which works comfortably with 50 concurrent on ScraperAPI Pro but requires Business tier on ZenRows and ScrapingBee.
If your workload is steady-state low-burst, the headline price tier is enough. If your workload is bursty (cron-driven full-catalog refreshes, event-triggered scrapes), upgrade for the concurrency before the credit count.
Webhook and async patterns
For batch workloads where you submit thousands of URLs and process results asynchronously, two patterns work:
- ScraperAPI’s batch endpoint accepts up to 50 URLs per submission and processes them in parallel. Results return inline as JSON arrays. Simple but caps at 50 URLs per call.
- ZenRows webhooks let you submit URLs with a callback URL; results POST back as they complete. Higher complexity but scales to tens of thousands of URLs per batch.
- ScrapingBee batch mode works similarly to ZenRows webhooks. Their async API is newer and the docs are still maturing.
For sub-100-URL batches, sync mode is simpler. For thousands of URLs, async webhooks are the only sane option; the wait time on a sync 1000-URL batch is too long.
Cost analysis at different scales
For three workload sizes:
10k requests/month, mostly basic HTML:
– ScraperAPI: $49/mo (free tier covers it)
– ZenRows: $69/mo (free tier covers it)
– ScrapingBee: $49/mo (free tier covers it)
– Winner: any, pick on success rate for your targets.100k requests/month, mixed targets including some premium:
– ScraperAPI: $149/mo (Pro tier)
– ZenRows: $129/mo (Pro tier)
– ScrapingBee: $99/mo (Freelance tier) but credits run out fast on premium
– Winner: ScraperAPI for predictability, ZenRows for Cloudflare-heavy mix.1M requests/month, heavy premium target use:
– ScraperAPI: $999/mo (Business)
– ZenRows: $499-999/mo (Business)
– ScrapingBee: $1499/mo (Business+)
– Winner: ZenRows by a clear margin.We cover the broader scraping API market in our best web scraping APIs 2026 review.
Common gotchas
- Credit-multiplier surprises. Targets reclassified as “premium” raise their multiplier silently. Track credit-burn-per-target weekly so you catch reclassifications before the bill arrives.
- Geo flag price tiers. All three charge extra credits for geo-targeted requests beyond default US/EU. ASEAN, MENA, and LATAM geos can 2-3x the per-request cost.
- JavaScript rendering on SPAs that auto-redirect. Some SPAs redirect mid-render and the API returns the redirect target’s HTML, not the original. Always check the final URL in the response.
- Sticky session uniqueness. All three pass session ID via a parameter; a typo or collision routes two workers to the same IP and corrupts both sessions. Generate session IDs from worker_id + timestamp to guarantee uniqueness.
- Response size truncation. ScraperAPI and ScrapingBee truncate responses over 5 MB by default. Pages with embedded base64 images can hit this. Specifically opt in to larger responses on plans that support them.
- Free trial concurrency caps. All three throttle free trials to 1-5 concurrent requests. Burst testing fails on the trial; results understate real production capability. Negotiate higher trial concurrency before benchmarking.
- Webhook flakiness on async APIs. ScraperAPI’s async batch mode delivers via webhooks that occasionally drop. Always have a polling fallback that catches missed deliveries.
- CAPTCHA solving included vs add-on. “Premium” tier on each vendor includes some CAPTCHA solving but not all types. hCaptcha and Turnstile are sometimes additional add-ons. Confirm before assuming.
When to use a different service entirely
If the comparison is closer than 5 points across all three on your specific targets, you may benefit from a different service entirely:
- For SERP only: SerpApi or DataForSEO outperform all three.
- For Amazon at extreme scale: Bright Data Amazon Scraper API is more cost-effective than any of the three.
- For LinkedIn: Bright Data LinkedIn Scraper API is the only one that works reliably.
- For full headless browser control: Browserbase managed Playwright.
We compare these alternatives in Bright Data vs Oxylabs vs Smartproxy: 2026 honest review and Apify vs Octoparse vs ParseHub.
Trial and testing
All three offer free trials:
- ScraperAPI: 5000 credits free, no credit card required
- ZenRows: 1000 credits free, no credit card required
- ScrapingBee: 1000 credits free, no credit card required
Use the trial credits on your actual target URLs, not on httpbin.org. The success rate variation between targets is large; testing on the wrong target gives you the wrong answer.
import requests import time API_CONFIGS = { "scraperapi": { "url": "https://api.scraperapi.com", "params_template": lambda url, key: {"api_key": key, "url": url, "render": "true", "premium": "true"}, }, "zenrows": { "url": "https://api.zenrows.com/v1/", "params_template": lambda url, key: {"apikey": key, "url": url, "js_render": "true", "premium_proxy": "true"}, }, "scrapingbee": { "url": "https://app.scrapingbee.com/api/v1/", "params_template": lambda url, key: {"api_key": key, "url": url, "render_js": "true", "premium_proxy": "true"}, }, } YOUR_TARGETS = [ "https://www.amazon.com/dp/B08N5WRWNW", "https://www.your-actual-target.com", ] KEYS = {"scraperapi": "...", "zenrows": "...", "scrapingbee": "..."} def test(service: str, samples: int = 50): config = API_CONFIGS[service] success = 0 latencies = [] for _ in range(samples): for target in YOUR_TARGETS: start = time.monotonic() try: resp = requests.get( config["url"], params=config["params_template"](target, KEYS[service]), timeout=60, ) latency = (time.monotonic() - start) * 1000 latencies.append(latency) if resp.status_code == 200 and len(resp.text) > 5000: success += 1 except Exception: pass print(f"{service}: success {success}/{samples*len(YOUR_TARGETS)}, median latency {sorted(latencies)[len(latencies)//2]:.0f}ms") for s in API_CONFIGS: test(s)What to skip
ScraperAPI’s lowest tier for hard targets: the basic pool struggles with anti-bot. Pay for premium or pick a different service.
ZenRows for simple HTML scraping: the premium pricing is overkill. Use ScraperAPI or roll your own with httpx.
ScrapingBee for high-volume Amazon: the 75x multiplier on Amazon makes the cost prohibitive at scale.
External authoritative reference: see the ZenRows API documentation for technical details on their parameters and pricing model.
FAQ
Q: which has the best uptime?
All three have 99.9%+ uptime SLAs and meet them in practice. Outages happen rarely; when they do, all three notify users via status page.Q: do they refund failed requests?
ScraperAPI refunds requests that return 4xx/5xx from their service. ZenRows refunds blocked requests automatically. ScrapingBee refunds on a per-request basis with a slightly stricter policy. Read the fine print before committing.Q: which is best for SERP?
None. Use SerpApi or DataForSEO. The general-purpose APIs are more expensive and less accurate for SERP than dedicated alternatives.Q: can I switch between them easily?
Yes. The APIs are similar enough that switching is a parameter rename and a base URL change. Many production setups use one as primary and another as failover.Q: which has the best documentation?
ScrapingBee. Clear examples, well-organized parameter reference, working code samples. ZenRows is a close second. ScraperAPI is functional but less polished.Q: do they support Asian targets well?
ScraperAPI and ZenRows both have Asian residential coverage on premium tiers. ScrapingBee’s Asian coverage is thinner. For Japanese, Korean, or Indonesian targets, do extensive trial testing because results vary.Q: which is best for high-frequency price monitoring?
ZenRows tends to win on per-success cost for repeated polling of e-commerce product pages. ScraperAPI is competitive on basic catalogs.Q: are there any with built-in dataset or marketplace features?
None of the three have a Bright Data Datasets equivalent. For pre-scraped data, look at Bright Data or Apify’s dataset offerings.Closing
ScraperAPI, ZenRows, and ScrapingBee are all production-quality scraping APIs in 2026. ScraperAPI is the safe default for general-purpose mid-tier scraping. ZenRows wins on Cloudflare-heavy and Amazon-heavy workloads. ScrapingBee wins on rendering quality and screenshot/PDF needs. Pick based on your specific target mix; the wrong choice can cost 3-5x more than the right one. For broader scraping API context see our competitor-comparisons category hub.
Related comparison: For Singapore-specific work, compare Smartproxy (now Decodo) against a real Singapore carrier network in our SMP vs Smartproxy comparison.
- Wrap each API behind a uniform
-
Best Go scraping libraries 2026 ranked
Best Go scraping libraries 2026 ranked
Best Go scraping libraries in 2026 occupy a niche that is small but unusually high-leverage. Go’s concurrency model (goroutines and channels) maps almost perfectly to the scraping problem, and Go’s compiled binary makes deployment dramatically simpler than Python or Node alternatives. The downside is library breadth: the Go scraping ecosystem has fewer options than Python’s, and the existing libraries are less actively maintained on average. For specific workloads (high-throughput HTTP scraping, distributed crawler workers, scraping infrastructure embedded in Go services), Go is the right choice and the libraries that exist are excellent. For one-off scrapers or projects that benefit from a rich ecosystem, Python or Node remain easier.
This guide ranks the Go scraping libraries actually worth using in 2026, with honest performance comparisons, clear use case mapping, and the gotchas specific to Go’s approach.
Why Go for scraping
Three reasons Go is interesting for scrapers:
Concurrency: a goroutine costs about 2 KB of stack memory. You can run 10,000+ concurrent goroutines on a modest server. Compared to Python’s coroutine overhead and Node’s event loop limits, Go’s concurrency is genuinely different in scale.
Compile-once deploy-anywhere: a Go binary is a single static file. Deployment to a new server or container is
scpand./scraper. No virtualenv, no node_modules, no version drift between dev and prod.HTTP performance: Go’s
net/httpstandard library is fast enough that “scraping” and “high-performance HTTP service” use the same toolkit. fasthttp pushes performance even further for extreme throughput needs.Three reasons Go is sometimes wrong:
Smaller library ecosystem: fewer parsers, fewer pre-built scrapers, less community content.
No native browser automation: Chromedp and Rod are good but not as polished as Playwright in Python or JavaScript.
Verbose for one-offs: Python’s
requeststwo-line scraper has no clean Go equivalent.HTTP clients
net/http (standard library)
The standard library client. Production-grade, well-documented, fast. Right choice for most scraping HTTP needs.
package main import ( "io" "net/http" "time" ) func fetch(url string) ([]byte, error) { client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } req.Header.Set("User-Agent", "Mozilla/5.0 ...") resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() return io.ReadAll(resp.Body) }Best for: most Go HTTP work. Default unless you have specific needs.
fasthttp
Aggressive performance-oriented HTTP library that bypasses some net/http abstractions for raw speed. 5-10x faster than net/http on benchmarks. The API is different (uses
fasthttp.Requestandfasthttp.Responseinstead of net/http types).import "github.com/valyala/fasthttp" func fetchFast(url string) ([]byte, error) { req := fasthttp.AcquireRequest() resp := fasthttp.AcquireResponse() defer fasthttp.ReleaseRequest(req) defer fasthttp.ReleaseResponse(resp) req.SetRequestURI(url) req.Header.SetUserAgent("Mozilla/5.0 ...") if err := fasthttp.Do(req, resp); err != nil { return nil, err } return resp.Body(), nil }Best for: extreme throughput needs (10k+ requests/sec), low-latency requirements.
resty
The popular convenience HTTP client wrapping net/http with a nicer API. Fluent builder pattern, JSON serialization, retry support. Slightly slower than raw net/http but more readable.
import "github.com/go-resty/resty/v2" client := resty.New().SetTimeout(10 * time.Second) resp, err := client.R(). SetHeader("User-Agent", "Mozilla/5.0"). Get("https://example.com")Best for: developer ergonomics, projects that benefit from convenience over absolute performance.
HTML parsers
GoQuery
The jQuery-style HTML parser. Cleanest API for Go HTML manipulation. Built on
golang.org/x/net/htmlunder the hood.import ( "github.com/PuerkitoBio/goquery" "strings" ) func parseTitles(html string) []string { doc, err := goquery.NewDocumentFromReader(strings.NewReader(html)) if err != nil { return nil } var titles []string doc.Find("h2.product-title").Each(func(i int, s *goquery.Selection) { titles = append(titles, s.Text()) }) return titles }Best for: most Go HTML parsing. Default choice.
golang.org/x/net/html
The standard parser GoQuery wraps. Direct use is verbose but available for custom AST manipulation.
Best for: low-level parsing needs, when you want zero dependencies.
colly’s parser
Colly framework includes its own HTML traversal which is less verbose than GoQuery for callback-driven scraping. Used in conjunction with Colly only.
Browser automation
Chromedp
The dominant Go browser automation library. Uses Chrome DevTools Protocol directly without intermediate libraries. Fast, well-maintained, but the API is verbose compared to Playwright.
import ( "context" "github.com/chromedp/chromedp" "time" ) func scrapeWithChrome(url string) (string, error) { ctx, cancel := chromedp.NewContext(context.Background()) defer cancel() ctx, cancel = context.WithTimeout(ctx, 30*time.Second) defer cancel() var title string err := chromedp.Run(ctx, chromedp.Navigate(url), chromedp.WaitVisible("h1.product-title"), chromedp.Text("h1.product-title", &title), ) return title, err }Best for: most Go browser automation. The default choice when you need a real browser.
Rod
A modern alternative to Chromedp with a more fluent API. Active development, strong feature parity with Playwright.
import "github.com/go-rod/rod" browser := rod.New().MustConnect() page := browser.MustPage("https://example.com").MustWaitLoad() title := page.MustElement("h1.product-title").MustText()Best for: developers who prefer Rod’s API ergonomics over Chromedp’s.
Playwright-go
The Microsoft Playwright API for Go. Newer and less mature than Chromedp/Rod but offers cross-browser (Firefox, WebKit) support that the Chrome-only alternatives lack.
Best for: cross-browser needs in Go, teams using Playwright in other languages.
Frameworks
Colly
The dominant Go scraping framework. Built-in caching, concurrency, request rate limiting, and HTML parsing callbacks. The right choice for crawler-heavy Go scrapers.
import "github.com/gocolly/colly/v2" c := colly.NewCollector( colly.AllowedDomains("example.com"), colly.Async(true), ) c.Limit(&colly.LimitRule{ DomainGlob: "*", Parallelism: 10, Delay: 100 * time.Millisecond, }) c.OnHTML("div.product", func(e *colly.HTMLElement) { fmt.Println(e.ChildText("h2.title")) }) c.OnHTML("a.next", func(e *colly.HTMLElement) { e.Request.Visit(e.Attr("href")) }) c.Visit("https://shop.example.com/page/1") c.Wait()Best for: large crawlers, the standard Go scraping framework.
Geziyor
Another Go scraping framework with similar feature set to Colly. Less popular but actively maintained.
Best for: Colly alternatives.
Comparison table
library layer speed learning curve best for net/http HTTP fast easy most HTTP work fasthttp HTTP fastest medium extreme throughput resty HTTP fast easy developer ergonomics GoQuery parser fast easy most HTML parsing golang.org/x/net/html parser fast hard custom AST work Chromedp browser mid medium most browser automation Rod browser mid medium Chromedp alternative Playwright-go browser mid medium cross-browser Colly framework fast medium most crawler work Geziyor framework fast medium Colly alternative Decision matrix: solopreneur, SMB, enterprise
profile scale recommended stack reasoning Solopreneur Go-curious <10k pages/day net/http + GoQuery Standard library + the one parser Indie scraper, single binary <500k pages/day net/http + GoQuery + Colly Framework value at this scale Indie extreme throughput <1M pages/day fasthttp + GoQuery When net/http becomes a bottleneck SMB scraping infra 1-10M pages/day Colly + Redis queue + custom workers Distribute across N binaries SMB JS-heavy <500k pages/day Chromedp + GoQuery post-parse Browser only when needed Embedded scraping in service varies net/http only Avoid framework imports inside larger services Enterprise data pipeline 10M+ pages/day Custom Go workers + Kafka + GoQuery Maximum control, minimum dependencies The right pattern for Go at scale is custom workers reading from a queue rather than a monolithic Colly process. Goroutines do the concurrency; Redis or NATS does the work distribution. This pattern scales linearly with worker count and survives single-machine failures cleanly.
Migration path: Python or Node to Go
Most Go migrations happen when Python or Node scrapers hit infrastructure limits at scale. The playbook:
- Identify the throughput bottleneck. If your Python scraper saturates one CPU core at 800 req/s, Go can run the same workload at 4000+ req/s on one core. If you are not CPU-bound, the migration may not pay off.
- Port one scraper end-to-end. Choose the highest-throughput single-target scraper as the migration pilot. Validate output equivalence on a sample.
- Keep Python or Node for orchestration. Many teams use Go for the scraper workers and Python for the data pipeline (Pandas, ML preprocessing). The tools do not have to match.
- Containerize and deploy in parallel. Run Go workers alongside Python workers reading from the same queue. Cut over by reducing Python worker count over a few weeks.
- Re-evaluate at six months. If the Go workers are stable and the throughput gain is real, migrate the rest. If they are not, the original choice was right.
The migration is rarely binary. Most production scrapers end up polyglot with Go for hot-path workers and Python for one-off and analytical work.
Performance benchmarks
Same workload as Python and Node benchmarks: 10,000 simple HTML pages from a local mirror, single Go binary.
stack total time requests/sec net/http (50 goroutines) 6s 1666 fasthttp (50 goroutines) 3s 3333 resty (50 goroutines) 8s 1250 Colly (default) 7s 1428 Chromedp (50 contexts) 110s 90 Go HTTP throughput is the highest of the three languages we benchmarked. fasthttp specifically is faster than even Node’s undici for this workload. Browser automation is similar across all languages because the bottleneck is browser execution.
Cost worked example
For a 1M-pages-per-day Go scraping workload (roughly 12 req/s sustained):
- 1 medium VPS ($40/mo, 8 vCPU, 16 GB)
- net/http + GoQuery + Colly stack (free)
- uTLS for TLS fingerprint impersonation when needed (free)
- Smartproxy/Decodo residential proxies (~$200/mo for ~25 GB)
- Redis on a small managed instance ($10/mo) for distributed work coordination
- PostgreSQL on a hosted instance ($25/mo)
Total: about $275/month for a workload that handles 30 million pages per month. The Python or Node equivalent would need 2-3x the compute capacity for the same throughput, raising infrastructure cost by $80-120/month. Go’s compiled binary also reduces deployment complexity (no language runtime, no virtualenv) and operational toil.
The break-even point where Go’s lower compute cost overcomes its higher development cost typically sits around 10M pages/month. Below that, Python or Node ergonomics usually win on total team productivity.
Stack recommendations
Most Go scraping: net/http + GoQuery + Colly. Standard library plus the two best community libraries. Adequate for almost everything.
Extreme throughput: fasthttp + GoQuery + Colly. When you need 10k+ HTTP requests per second per machine.
Browser-required scraping: Chromedp + GoQuery (for parsing extracted HTML). Use Chromedp for JS execution, GoQuery for the parsing because it is more ergonomic.
Distributed scraping: net/http + GoQuery + custom code with Redis queues. Colly does not have great distributed support; for multi-machine scrapers you build the coordination layer yourself.
Scraping inside a larger Go service: net/http directly. Avoid pulling in framework overhead for embedded scraping inside a service that does other things.
Idiomatic Go scraper template
A modern Go scraper using standard libraries:
package main import ( "context" "fmt" "io" "net/http" "strings" "sync" "time" "github.com/PuerkitoBio/goquery" ) type Product struct { Name string Price string URL string } func fetchPage(ctx context.Context, url string) (string, error) { req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { return "", err } req.Header.Set("User-Agent", "Mozilla/5.0") client := &http.Client{Timeout: 15 * time.Second} resp, err := client.Do(req) if err != nil { return "", err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) return string(body), err } func parseProducts(html string) []Product { doc, err := goquery.NewDocumentFromReader(strings.NewReader(html)) if err != nil { return nil } var products []Product doc.Find("div.product-card").Each(func(i int, s *goquery.Selection) { products = append(products, Product{ Name: s.Find("h2.title").Text(), Price: s.Find("span.price").Text(), URL: s.Find("a").AttrOr("href", ""), }) }) return products } func scrapeAll(urls []string, concurrency int) []Product { sem := make(chan struct{}, concurrency) var wg sync.WaitGroup var mu sync.Mutex var allProducts []Product for _, url := range urls { wg.Add(1) go func(u string) { defer wg.Done() sem <- struct{}{} defer func() { <-sem }() html, err := fetchPage(context.Background(), u) if err != nil { fmt.Println("error:", err) return } products := parseProducts(html) mu.Lock() allProducts = append(allProducts, products...) mu.Unlock() }(url) } wg.Wait() return allProducts } func main() { urls := []string{"https://example.com/p/1", "https://example.com/p/2"} products := scrapeAll(urls, 20) for _, p := range products { fmt.Printf("%+v\n", p) } }This pattern handles 1500+ pages per minute on a small VPS with proper concurrency control.
Distributed scraper architecture
For workloads that exceed one machine, the canonical Go scraper architecture is:
- Coordinator service that pushes URLs to a queue (Redis Streams, NATS JetStream, or Kafka).
- Worker pool of N stateless Go binaries, each consuming from the queue, scraping in parallel goroutines, and writing results to a sink (Postgres, S3, Kafka).
- Health and metrics exposed via Prometheus endpoints on each worker; scraped via a central Prometheus + Grafana stack.
- Dead-letter queue for URLs that fail repeatedly, picked up by a slower retry process or surfaced for manual investigation.
This pattern scales linearly: doubling worker count doubles throughput up until the target rate-limits or the queue itself bottlenecks. With NATS or Kafka, the queue layer easily handles 100k messages/sec, far beyond what most scrapers need.
Common mistakes to avoid
Forgetting to close response bodies: every HTTP response body must be closed or you leak file descriptors. The
defer resp.Body.Close()pattern is essential.Unbounded goroutine spawning: launching one goroutine per URL without a semaphore exhausts memory and overwhelms target sites. Use a buffered channel as a semaphore.
Using fasthttp when you do not need it: fasthttp’s API is different from net/http and the integration cost is real. For most workloads, net/http is fast enough.
Ignoring context cancellation: pass
context.Contextthrough your scraper functions so you can cancel cleanly on shutdown signals.Trying to use Python-style async patterns: Go’s concurrency primitives (goroutines, channels, sync.WaitGroup) are different from async/await. Embrace them rather than fighting them.
We cover the Python and Node alternatives in our best Python scraping libraries 2026 and best Node.js scraping libraries 2026 reviews.
External authoritative reference: the Go net/http documentation covers the standard library client.
Common gotchas
- Goroutine leaks. Goroutines started without a clear exit path can leak forever if their channel never closes. Always have a
context.Done()check or aselectwith a timeout case. - net/http connection reuse defaults. The default Transport reuses connections, which is good for performance but bad if you want each request from a fresh proxy. For per-request isolation, set
Transport.DisableKeepAlives = true. - fasthttp’s API allocations.
fasthttp.RequestandResponseare pooled; you mustAcquireandReleasethem. ForgettingReleasecauses memory growth that looks like a leak. - GoQuery selector syntax differences. GoQuery uses CSS selectors but does not support all jQuery extensions.
:contains()is supported,:has()is not. Test your selectors against the actual DOM before assuming. - Chromedp context cancellation. Cancelling the parent context kills all in-flight Chrome operations, but the headless Chrome process can survive. Always call
chromedp.Cancel(ctx)explicitly to ensure cleanup. - JSON unmarshaling silent failures. Unknown fields are silently dropped by
json.Unmarshal. If your target’s response shape changes, you may not notice. UseDisallowUnknownFields()on the decoder during development. - Slice append concurrency. Multiple goroutines appending to the same slice corrupt it. Use a
sync.Mutexor a channel-based aggregator. - Colly OnHTML callback ordering. Multiple
OnHTMLhandlers for overlapping selectors fire in registration order, not in DOM order. Test handler ordering if you depend on it.
When to use Go vs Python vs Node
consideration best language highest HTTP throughput per machine Go richest ecosystem Python best browser automation Python or Node (Playwright) simplest deployment Go (single binary) smallest learning curve Python best for embedded scraping in services Go largest community of scraping content Python AI/LLM integration Python For dedicated scraping projects that scale and benefit from compiled performance, Go is excellent. For one-offs and projects requiring rich ecosystem support, Python wins. For Node-shop infrastructure, Node Crawlee fits naturally.
FAQ
Q: Colly or write my own?
For projects with link-following, deduplication, and rate-limiting needs across thousands of pages, Colly saves significant code. For simple scrapers with a known URL list, raw net/http + GoQuery is enough.Q: Chromedp or Rod or Playwright-go?
Chromedp is the safe default with the most production usage. Rod has a nicer API. Playwright-go is right when you need Firefox or WebKit. Performance is similar across all three.Q: how do I handle TLS fingerprinting in Go?
Go’s TLS stack does not have first-class fingerprint impersonation. The closest options areutls(uTLS) which mimics specific browser TLS handshakes, and routing through a proxy that handles fingerprinting.Q: is fasthttp worth the complexity?
For most workloads, no. fasthttp gives you an extra 2-5x throughput at the cost of API divergence from the standard library. Use it when you have measured a performance need that net/http cannot meet.Q: does Go have an equivalent to Scrapy?
Colly is the closest. Less batteries-included than Scrapy but covers the core crawler patterns.Q: how do I handle proxies in Go?
SetTransport.Proxyon yourhttp.Client. For per-request proxy rotation, build a custom Transport that selects a proxy from a pool. Colly accepts a proxy switcher function natively.Q: are there structured-data extraction libraries?
A few exist (go-rod/rodfor browser,tdewolff/parsefor streaming HTML). For strongly typed extraction, write a struct and unmarshal CSS selectors into it manually with reflection or code generation.Q: is Go’s gc a problem for long-running scrapers?
Generally no. Go’s GC has been excellent since 1.14 with sub-millisecond pauses. The main GC concern is allocating in tight loops; reuse buffers and pool objects withsync.Poolif you see GC pressure.Closing
Go scraping in 2026 is the right choice for high-throughput dedicated scraping infrastructure, distributed crawler workers, and embedded scraping inside Go services. The ecosystem is smaller than Python’s but the libraries that exist are excellent. net/http + GoQuery + Colly is the standard stack; fasthttp and Chromedp cover specialized needs. For broader scraping infrastructure see our dev-tools-projects category hub.
-
Best Node.js scraping libraries 2026
Best Node.js scraping libraries 2026
Best Node scraping libraries in 2026 occupy a different ecosystem than Python’s. Node’s event-loop architecture is naturally async-first, so concurrency comes for free. Browser automation has stronger native fit because Puppeteer was originally a Node-only library and the JavaScript-runtime-controlling-JavaScript story is uniquely tight. The Node scraping market has consolidated around a smaller list of high-quality libraries than Python’s, but each library is more polished and the gaps are smaller. The four-layer model still applies: HTTP client, browser automation, HTML parser, framework. Picking the right combination per layer determines whether your scraper handles 100 or 10,000 requests per second.
This guide ranks the Node.js scraping libraries actually worth using in 2026, with honest performance comparisons, clear use case mapping, and the gotchas that surprise developers coming from Python.
HTTP clients
undici
Node’s modern HTTP client, developed by the Node.js core team. Faster than every alternative by 2-3x for high-concurrency workloads. The standard
fetchglobal in modern Node uses undici under the hood.import { fetch } from 'undici'; async function scrape(url) { const resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0 ...' }, }); return resp.text(); }Best for: any new project, high-concurrency workloads, the default unless you have specific needs.
got
The popular HTTP client before undici took over. Excellent retry, redirect, and cookie handling. Slightly slower than undici but more feature-complete out of the box.
import got from 'got'; const html = await got('https://example.com', { retry: { limit: 3 }, timeout: { request: 10000 }, }).text();Best for: existing got codebases, projects that benefit from got’s batteries-included extras.
axios
The classic. Sync-style promise API that everyone knows. Slower than undici and got. Still ubiquitous because of legacy familiarity.
Best for: existing axios codebases, teams that already know its API.
node-fetch
The original Node fetch polyfill, now mostly obsolete since native fetch landed in Node 18+.
Best for: legacy projects, nothing else.
Browser automation
Playwright
Same library as Python; the JavaScript version is actually the reference implementation. Cleaner API in JavaScript than Python because of TypeScript autocompletion. Best browser automation framework in any language.
import { chromium } from 'playwright'; const browser = await chromium.launch(); const context = await browser.newContext({ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', }); const page = await context.newPage(); await page.goto('https://target.example.com'); const title = await page.locator('h1.product-title').textContent(); await browser.close();Best for: most modern browser automation in Node, multi-browser needs.
Puppeteer
The Google-maintained Chrome automation library. Slightly cleaner Chrome-specific features than Playwright, similar overall capability. The puppeteer-extra plugin ecosystem (especially stealth plugin) is more mature than Playwright’s equivalents.
Best for: Chrome-only workflows, projects using puppeteer-extra plugins.
Crawlee
Apify’s scraping framework with built-in browser support. Wraps Playwright/Puppeteer with crawler-style ergonomics. We cover it under frameworks below.
HTML parsers
Cheerio
The jQuery-syntax server-side parser. The dominant Node HTML parser. Fast (built on parse5 or htmlparser2), familiar API for anyone who used jQuery.
import * as cheerio from 'cheerio'; const $ = cheerio.load(html); const titles = $('h2.product-title').map((i, el) => $(el).text()).get();Best for: most HTML parsing in Node, jQuery-familiar developers.
parse5
The lower-level HTML parser that Cheerio uses under the hood. Direct use is rare but available for custom AST work.
Best for: custom HTML manipulation, building higher-level tools.
htmlparser2
Streaming HTML parser, very fast on large documents. Used by Cheerio when configured for it. Direct use for stream-based parsing.
Best for: parsing very large HTML documents in stream mode.
linkedom
Modern alternative offering full DOM API (not just jQuery-style). If your code expects
document.querySelectorsemantics, linkedom feels native.import { parseHTML } from 'linkedom'; const { document } = parseHTML(html); const titles = Array.from(document.querySelectorAll('h2.product-title')).map(el => el.textContent);Best for: developers who prefer DOM API over jQuery API, code shared between client and server.
Frameworks
Crawlee
Apify’s modern scraping framework. The Node version is the original; the Python port came later. Excellent abstractions for HTTP and browser scraping with the same Crawler interface, built-in queue management, dedupe, retry logic, and proxy rotation.
import { CheerioCrawler } from 'crawlee'; const crawler = new CheerioCrawler({ async requestHandler({ request, $ }) { console.log(`Scraping ${request.url}`); const titles = $('h2.product-title').map((i, el) => $(el).text()).get(); await crawler.pushData({ url: request.url, titles }); }, maxRequestsPerCrawl: 1000, maxConcurrency: 10, }); await crawler.run(['https://shop.example.com/page/1']);Best for: most modern Node scraping projects that need framework benefits.
x-ray
Older declarative scraping framework. Still works but rarely chosen for new projects.
Best for: legacy x-ray codebases.
Apify SDK
Crawlee’s parent SDK with additional Actor and platform features. Right choice if deploying to Apify cloud.
Best for: Apify platform deployments.
Comparison table
library layer speed learning curve best for undici HTTP fastest easy most new projects got HTTP fast easy retry-heavy needs axios HTTP mid easy legacy codebases node-fetch HTTP mid easy nothing in 2026 Playwright browser mid medium most browser automation Puppeteer browser mid medium Chrome-only, stealth plugins Cheerio parser fast easy most parsing parse5 parser fast hard custom AST work htmlparser2 parser fastest medium very large docs, streaming linkedom parser fast easy DOM-API preference Crawlee framework fast medium modern crawler projects x-ray framework mid easy legacy Decision matrix: solopreneur, SMB, enterprise
profile scale recommended stack reasoning Solopreneur learning <10k pages/day native fetch + Cheerio Zero dependencies, modern defaults Indie scraper <500k pages/day undici + Cheerio + p-limit Best HTTP perf, simple flow control Indie JS-heavy <100k pages/day Playwright + Cheerio post-parse Browser only when needed SMB crawler 500k-10M pages/day Crawlee CheerioCrawler Framework manages queue, dedupe, retry SMB anti-detect 100k-1M pages/day Puppeteer + puppeteer-extra-plugin-stealth Stealth ecosystem maturity Enterprise 10M+ pages/day Crawlee on K8s + custom middleware Volume justifies platform investment Hybrid HTTP/JS varies Crawlee (CheerioCrawler + PlaywrightCrawler) Same dataset across two modes The Node ecosystem rewards convergence: most teams end up on undici + Cheerio for HTTP and Playwright + stealth plugins for browser. Crawlee adds value above 500k pages/day; below that, hand-rolled async with
p-limitis simpler and fast enough.Migration path: axios + cheerio to undici + Cheerio
Most legacy Node scrapers run on axios because it was the dominant HTTP client of the 2018-2022 era. Modernizing to undici is straightforward and yields a 2-3x throughput improvement:
- Replace
axios.get(url, opts)withawait fetch(url, opts)fromundici. The API differs slightly (response body via.text()/.json()instead of.data). - Replace axios interceptors with explicit retry wrappers. undici does not have an interceptor system; use a small wrapper function for retry, logging, and metrics.
- Update timeout handling to use
AbortSignal.timeout(ms)instead of axios’stimeoutoption. - Benchmark the same workload before and after. Expect 2-3x improvement on concurrent request throughput.
- Keep axios for any code that uses interceptors heavily (auth refresh patterns, request signing) where the cost of unwinding interceptor logic outweighs the perf gain.
A typical Node scraper migration completes in a day. The performance gain often unblocks scaling work that was on the roadmap for distributed infrastructure.
Performance benchmarks
Same workload as the Python benchmarks: 10,000 simple HTML pages from a local mirror, single Node process.
stack total time requests/sec native fetch (50 concurrency) 8s 1250 undici (50 concurrency) 7s 1428 got (50 concurrency) 11s 909 axios (50 concurrency) 14s 714 Playwright (50 concurrent contexts) 88s 113 Crawlee CheerioCrawler 9s 1111 Node beats Python on raw HTTP throughput thanks to its event loop architecture. The browser automation gap is similar in both languages because the bottleneck is browser execution, not the host runtime.
Cost worked example
For a 100k-pages-per-day Node scraping workload on mixed protected and unprotected targets:
- 1 small VPS ($20/mo, 4 vCPU, 8 GB)
- undici + Cheerio + p-limit stack (free, Node only)
- node-libcurl when TLS impersonation is needed (free, requires native build)
- Smartproxy/Decodo residential proxies (~$50/mo for 5 GB)
- PostgreSQL on a hosted instance ($25/mo)
- Optional: ZenRows fallback for hard surfaces (~$69/mo)
Total: about $95-165/month depending on the API fallback. Node throughput is higher than Python on raw HTTP, which lets you pack more work into the same VPS; expect to need ~30% less compute capacity than the equivalent Python deployment.
The other Node-specific cost dimension is RAM. Node processes typically run 200-300 MB at scraping idle and grow with concurrent contexts. For a single-process scraper, 8 GB RAM is plenty; for distributed multi-worker setups, prefer many small workers over few large ones to limit blast radius from leaks.
Stack recommendations
Small project, scripts: native fetch + Cheerio. Built into modern Node, no dependencies, fast.
Medium project, no JS needs: undici + Cheerio. Fastest HTTP client + standard parser. Add
tenacity-style retry via simple wrapper.JavaScript-heavy targets: Playwright + Cheerio (parse the extracted HTML with Cheerio for speed instead of using Playwright’s slower DOM querying).
Large crawler with link-following: Crawlee. Built-in queue management saves you from writing your own.
Anti-bot heavy targets: Puppeteer with puppeteer-extra-plugin-stealth. The stealth plugin ecosystem is more mature for Puppeteer than for Playwright in Node.
Hybrid HTTP + browser: Crawlee with multiple crawler classes (CheerioCrawler for HTTP-only pages, PlaywrightCrawler for JS-heavy pages, both writing to the same dataset).
Crawlee deep dive
Crawlee deserves a closer look because it has matured into the de-facto Node scraping framework. Its three crawler classes cover the spectrum:
- CheerioCrawler: HTTP-only, uses got (or undici under the hood) and Cheerio. Fast, low-resource. The right default for HTTP scraping.
- PlaywrightCrawler: full browser automation with Playwright. Highest resource cost but handles any JavaScript.
- PuppeteerCrawler: same as Playwright but using Puppeteer. Choose this if your team prefers Puppeteer’s API or uses puppeteer-extra plugins.
All three share the same
RequestQueue,Dataset, andKeyValueStoreabstractions, which means you can switch between HTTP and browser modes per request without changing your data layer. A typical pattern is to start with CheerioCrawler, fall back to PlaywrightCrawler when the HTML is missing the data you need, and store both kinds of results in the same Dataset.Crawlee’s
RequestQueuesupports SQLite, MongoDB, and the Apify cloud as backends. SQLite works for single-process crawlers; MongoDB works for distributed crawlers across machines. The cloud backend gives you a managed queue with no operational overhead.Modern async patterns
Node’s async syntax is cleaner than Python’s for typical scraping patterns:
import { fetch } from 'undici'; import * as cheerio from 'cheerio'; import pLimit from 'p-limit'; async function fetchPage(url, retries = 3) { for (let attempt = 0; attempt < retries; attempt++) { try { const resp = await fetch(url, { signal: AbortSignal.timeout(15000), }); if (resp.status === 200) { return await resp.text(); } if (resp.status === 429 || resp.status === 503) { await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000)); continue; } return null; } catch (err) { if (attempt === retries - 1) throw err; await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000)); } } } function parseProducts(html) { if (!html) return []; const $ = cheerio.load(html); return $('div.product-card').map((i, el) => ({ name: $(el).find('h2.title').text(), price: $(el).find('span.price').text(), })).get(); } async function scrapeAll(urls, concurrency = 20) { const limit = pLimit(concurrency); const results = await Promise.all( urls.map(url => limit(async () => { const html = await fetchPage(url); return parseProducts(html); })) ); return results.flat(); }This pattern handles 1000+ pages per minute on a modest VPS with retries and concurrency control built in.
Persistence and storage in Node
Node scrapers benefit from a few storage patterns specific to JavaScript ecosystems:
- better-sqlite3 for synchronous local storage. Faster than the async
sqlite3library for write-heavy workloads because it avoids async overhead. - Knex or Prisma for typed Postgres access. Both work well; Prisma’s TypeScript types are stronger but Knex is lighter.
- Crawlee KeyValueStore + Dataset. When using Crawlee, prefer its built-in storage abstractions; they handle large blobs and structured records cleanly.
- DuckDB-WASM for in-process analytics. When you want to query scraped data without a database server, DuckDB now ships a Node binding that lets you run SQL on Parquet or local arrays.
For very large output volumes, stream writes to S3 / R2 with
@aws-sdk/client-s3MultipartUpload rather than collecting everything in memory and uploading at the end.Common mistakes to avoid
Using axios in 2026: it works but is slower than undici and got. New projects should default to undici.
Forgetting AbortSignal.timeout: Node’s native fetch does not have a default timeout. Without one, your scraper hangs on slow targets indefinitely.
Loading huge HTML strings into Cheerio at once: for documents over 10 MB, use htmlparser2 in streaming mode.
Running too many browser contexts in one Node process: Node memory grows fast with many Playwright contexts. Stay under 50 concurrent contexts per process.
Ignoring back-pressure in Crawlee: Crawlee’s queues can grow unboundedly if you push faster than you consume. Set
maxRequestsPerCrawlandmaxConcurrencyappropriately.We cover the Python equivalent in our best Python scraping libraries 2026 review.
Common gotchas
- Native fetch lacks default timeout. Without
AbortSignal.timeout(), your scraper hangs on slow targets indefinitely. Always set a timeout. - undici keep-alive defaults. undici defaults to keep-alive connections. For one-off scripts, this can leave the process hanging waiting for sockets. Use
Agent({ keepAliveTimeout: 1 })or callagent.close()at script end. - Cheerio re-parse cost. Each call to
cheerio.load()re-parses the HTML. For many extractions on the same document, parse once and pass$around. - Playwright newPage vs newContext.
newPage()reuses the parent context’s cookies;newContext()creates a fresh storage state. UsenewContext()per scrape to isolate cookies; many subtle bugs come from cookie cross-contamination. - Crawlee request handler errors. A throw inside
requestHandlerretries the request by default. If the error is permanent (404, parse failure), callrequest.noRetry = trueto skip the retry queue. - JSON parsing with native fetch.
await resp.json()throws on empty body; wrap in try/catch or checkresp.okfirst. - EventEmitter memory leaks. Browser launches that emit
console,request, orresponseevents accumulate listeners if you do not clean them up. Usepage.removeAllListeners()before close or use named handler functions you can remove explicitly. - TLS hardening on undici. Some targets refuse TLS 1.2 connections. undici defaults to negotiating up; if you see handshake errors, force
connect: { tls: { minVersion: 'TLSv1.3' } }.
TypeScript vs JavaScript
For new projects, TypeScript is the right choice. The HTTP and parsing libraries all ship with strong type definitions. The Playwright API in TypeScript is a different developer experience than JavaScript.
import { chromium, Browser, Page } from 'playwright'; async function scrape(browser: Browser, url: string): Promise<string | null> { const page: Page = await browser.newPage(); try { await page.goto(url); return await page.locator('h1').textContent(); } finally { await page.close(); } }The autocompletion and refactoring support pay off within the first week of any non-trivial project.
External authoritative reference: the Node.js documentation on the global fetch covers the standard HTTP client.
Bun and Deno alternatives
Bun and Deno both ship with built-in fetch and run all the libraries above. Bun is notably faster than Node for HTTP-heavy workloads (about 1.5-2x in our testing). Deno’s permission model is interesting for scraping isolation but the ecosystem is smaller.
For most teams, Node remains the right default in 2026 because library compatibility is broadest. We cover the alternatives in our forthcoming guides on Bun and Deno scraping.
FAQ
Q: Cheerio or jQuery selectors?
Cheerio implements jQuery-style selectors server-side. The API is essentially identical. Use Cheerio in Node; do not import actual jQuery server-side.Q: should I use Crawlee or write my own crawler?
For projects under 1000 pages, write your own with undici + Cheerio + p-limit. For larger crawls with link-following, dedupe, and retry needs, Crawlee saves significant code.Q: Puppeteer or Playwright?
Playwright is technically better for new projects: cleaner API, multi-browser, better auto-waiting. Puppeteer has the puppeteer-extra-plugin-stealth ecosystem advantage which still matters for some anti-detect work.Q: how do I handle TLS fingerprinting in Node?
Node does not have a great equivalent to Python’s curl_cffi yet. The closest options arenode-libcurl(libcurl bindings for Node) or routing through a proxy that handles TLS fingerprinting on your behalf.Q: is JSDOM useful for scraping?
JSDOM is heavier than Cheerio because it implements the full DOM API including layout. For scraping where you do not need actual JavaScript execution, Cheerio is faster. JSDOM is the right choice when you want to execute scripts on a parsed document without a full browser.Q: how do I integrate proxies?
With undici, use aProxyAgent. With Playwright, passproxytochromium.launch(). Crawlee has built-in proxy rotation across a pool. Avoid manual proxy management; use the built-in tools wherever possible.Q: is Bun production-ready for scraping?
Yes for most use cases. Bun’s built-in fetch and HTML parser are excellent. The remaining gaps are around obscure npm packages with native dependencies that have not been compiled for Bun. Test your dependency tree before committing to Bun in production.Q: what is the cleanest way to handle pagination?
Wrap your fetch in an async generator that yields pages until a stop condition. Async generators in Node compose nicely withfor awaitloops and avoid materializing all pages in memory.Closing
The Node.js scraping stack in 2026 is mature and stable. undici for HTTP, Cheerio for parsing, Playwright for browser automation, Crawlee for crawler frameworks. The ecosystem moves slower than Python’s but each piece is more polished. Match the stack to the workload and Node will outperform Python on raw HTTP throughput while matching it on browser automation. For broader scraping infrastructure see our dev-tools-projects category hub.
- Replace
-
Best Python scraping libraries 2026: Scrapy, BS4, more
Best Python scraping libraries 2026: Scrapy, BS4, more
Best Python scraping libraries in 2026 cover a stack that has matured significantly since the requests + BeautifulSoup era. The HTTP client layer has been split into a dozen options optimized for different use cases. Browser automation has consolidated around Playwright. Parsing has stabilized on lxml under the hood with multiple frontend options. The framework layer sees Scrapy holding its dominance for crawling-heavy use cases and Crawlee gaining ground as a modern alternative. Choosing the right combination of libraries determines whether your scraper runs at 10 requests per second or 1000, whether it survives anti-bot fingerprinting, and how much code you write to do straightforward things.
This guide ranks the Python scraping libraries actually worth using in 2026, organized by what they do, with honest performance comparisons and clear guidance on which to pick for which workload.
The four layers of a Python scraper
Every scraper has four layers, regardless of framework:
- HTTP client: makes the actual network requests
- Browser automation (optional): when JavaScript execution is needed
- HTML parser: extracts data from the response
- Orchestration framework (optional): handles concurrency, retries, queues, pipelines
Different libraries dominate each layer. The right scraper picks the best library per layer rather than committing to one library for everything.
HTTP clients
requests
The classic. Synchronous, simple, mature. Still the right choice for one-off scripts and learning. Performance is the worst of the modern options because it is sync-only.
import requests resp = requests.get("https://example.com", headers={"User-Agent": "..."}, timeout=10) print(resp.text)Best for: scripts, prototypes, learning, anything where async is overkill.
httpx
The modern requests replacement. Supports both sync and async, HTTP/2 by default, type-hinted, and dramatically faster than requests for any concurrent workload. The drop-in replacement for requests in most code.
import httpx import asyncio async def fetch(url: str): async with httpx.AsyncClient(http2=True, timeout=10) as client: resp = await client.get(url) return resp.text # concurrent fetching async def main(): urls = ["https://example.com/page/1", "https://example.com/page/2"] return await asyncio.gather(*[fetch(u) for u in urls])Best for: any new project, async workloads, HTTP/2 support, type safety.
aiohttp
The async-first HTTP client. Older than httpx but still excellent. Slightly faster than httpx for high concurrency. The websocket support is best in class.
Best for: high-concurrency async workloads, websocket-heavy use cases.
curl_cffi
The TLS-fingerprint-aware HTTP client. Wraps libcurl with browser-impersonation features so your TLS handshake looks like real Chrome, Firefox, or Safari. The right choice for any target with TLS fingerprinting (Cloudflare, DataDome, Akamai).
from curl_cffi import requests # impersonates Chrome 120 TLS fingerprint resp = requests.get( "https://target.example.com", impersonate="chrome120", timeout=10, ) print(resp.text)Best for: bypassing TLS fingerprinting, scraping sites that detect Python’s default TLS.
urllib3
The HTTP foundation that requests and httpx both use under the hood. Rarely used directly except for very low-level needs.
Best for: when you need fine-grained control of connection pools.
HTML parsers
lxml
The fast XML/HTML parser written in C. Underpins almost every other parser. Direct lxml use is fastest but the API is uglier than BeautifulSoup.
from lxml import html tree = html.fromstring(html_content) titles = tree.xpath("//h2[@class='product-title']/text()")Best for: high-performance parsing, XPath-heavy extraction.
BeautifulSoup4
The friendly parser. Slower than lxml directly but has the most readable API. The standard configuration uses lxml as the underlying parser, so the speed gap is smaller than people assume.
from bs4 import BeautifulSoup soup = BeautifulSoup(html_content, "lxml") titles = [t.text for t in soup.select("h2.product-title")]Best for: most general-purpose parsing, readable code, mixed CSS/find patterns.
selectolax
The fastest Python HTML parser by a wide margin. C-based, supports CSS selectors with a minimal API. Roughly 5-10x faster than BeautifulSoup on typical pages.
from selectolax.parser import HTMLParser tree = HTMLParser(html_content) titles = [n.text() for n in tree.css("h2.product-title")]Best for: high-volume parsing where every millisecond matters.
parsel
Scrapy’s parser, available standalone. Combines XPath, CSS, and regex selectors with a clean API.
Best for: Scrapy users wanting the same API outside Scrapy.
Browser automation
Playwright
The current best browser automation framework. We covered it in detail in best headless browser frameworks 2026.
Best for: modern browser automation, multi-browser support.
Selenium
The elder framework. Still solid for cross-browser needs. Verbose but well-documented.
Best for: legacy projects, multi-language teams sharing test infrastructure.
Pyppeteer (less recommended)
Python port of Puppeteer. Less actively maintained than Playwright. Avoid for new projects.
Frameworks
Scrapy
The dominant Python scraping framework. Async by design (since 2.0), built-in queue management, middleware system, item pipelines, and crawl rules. The right choice for crawler-heavy workloads where you are following links across thousands of pages.
import scrapy class ProductSpider(scrapy.Spider): name = "products" start_urls = ["https://shop.example.com/category/widgets"] def parse(self, response): for product in response.css("div.product"): yield { "name": product.css("h2::text").get(), "price": product.css("span.price::text").get(), "url": product.css("a::attr(href)").get(), } next_page = response.css("a.next::attr(href)").get() if next_page: yield response.follow(next_page, self.parse)The downside: Scrapy’s mental model is heavier than other frameworks. You learn callbacks, middleware, settings, items, and pipelines. For simple scrapers this is overkill.
Best for: large crawl projects, structured data extraction at scale, when you actually need a framework.
Crawlee
The newer framework from Apify, with a Pythonic API and built-in browser support. More approachable than Scrapy for newcomers. Supports HTTP and browser modes from the same crawler class.
Best for: modern projects that want framework benefits without Scrapy’s learning curve.
Pyspider
Older framework with a web UI for managing scrapers. Less actively maintained but still works for some use cases.
Best for: legacy systems, niche use cases needing visual management.
Comparison table
library layer sync/async speed learning curve best for requests HTTP sync slow easy scripts, prototypes httpx HTTP both fast easy most new projects aiohttp HTTP async fast medium high-concurrency async curl_cffi HTTP sync fast easy TLS fingerprint bypass BeautifulSoup4 parser sync mid easy general parsing lxml parser sync fast medium high-performance XPath selectolax parser sync fastest easy extreme volume parsing parsel parser sync fast easy Scrapy users Playwright browser both mid medium JS-heavy targets Selenium browser sync (mostly) slow medium legacy Scrapy framework async fast hard large crawls Crawlee framework async fast medium modern, browser-friendly Decision matrix: solopreneur, SMB, enterprise
profile scale recommended stack reasoning Solopreneur learning <1k pages/day requests + BeautifulSoup4 Simple, beginner-friendly Indie scraper (basic) <100k pages/day httpx + selectolax Async, fast, modern Indie scraper (anti-bot) <100k pages/day curl_cffi + selectolax TLS impersonation included SMB crawler 100k-10M pages/day Scrapy + curl_cffi middleware + selectolax Framework value at this scale SMB JS-heavy 10k-1M pages/day Crawlee or Playwright + httpx fallback Hybrid HTTP/browser ergonomics Enterprise pipeline 10M+ pages/day Scrapy on K8s + custom middleware + dedicated parsers Full ops + custom optimization Single-source ETL varies httpx + lxml direct XPath Tight, predictable, performant The most expensive mistake is over-frameworking small jobs (Scrapy for 200 pages) and under-frameworking large jobs (raw httpx loop for 10M URLs). Match the framework weight to the actual workload.
Migration path: requests + BS4 to httpx + selectolax
Most legacy Python scrapers can be modernized in a day with significant performance gains. The playbook:
- Wrap your fetch function in an async signature even before changing implementation. This isolates the migration scope.
- Replace
requests.getwithhttpx.AsyncClient.get. Most code translates 1:1; the main change isawaitkeywords and the async context manager. - Switch parser to selectolax. CSS selectors translate directly from BeautifulSoup; XPath users stay on lxml. Expect 5-10x parse speedup.
- Add concurrency with
asyncio.Semaphoreto bound parallel requests. Start at 10 and tune based on target tolerance. - Benchmark against original with the same input set. A typical migration shows 15-30x throughput improvement.
The whole migration usually takes one engineer-day for a single-purpose scraper, two days for a multi-target codebase. The throughput gain often eliminates the need for distributed scaling that was on the roadmap.
Performance benchmarks
We benchmarked HTTP fetching of 10,000 simple HTML pages from a local mirror, single machine, no network bottleneck.
stack total time requests/sec requests (sync) 240s 42 httpx (async, 50 concurrency) 12s 833 aiohttp (50 concurrency) 11s 909 curl_cffi (50 concurrency) 14s 714 Scrapy (default settings) 18s 555 Playwright (50 concurrent contexts) 95s 105 Async HTTP is 20x faster than sync. Browser automation is 8-10x slower than HTTP. The difference is essentially the cost of running JavaScript and rendering, which is unavoidable for SPAs.
Choosing between async frameworks
Python’s async ecosystem fragmented for years between asyncio (standard library), trio (alternative event loop with cleaner cancellation semantics), and AnyIO (a compatibility layer). For scraping, asyncio is the right default because every major HTTP and parser library targets it. trio remains technically superior for cancellation safety but the ecosystem cost is real.
The other choice is between asyncio’s default event loop and uvloop (a Cython-accelerated drop-in replacement). For HTTP-bound scrapers, uvloop yields a 2-4x throughput improvement essentially for free:
import asyncio import uvloop uvloop.install() # do this before any asyncio code # rest of your scraperThe two-line installation gets you the benefit. The only caveat is that uvloop does not work on Windows; cross-platform code needs a try/except around the install call.
Stack recommendations by use case
Small project, learning, scripts: requests + BeautifulSoup4. Simple, well-documented, slow but adequate.
Medium project, production, no JavaScript needs: httpx (async) + selectolax. Fast, modern, scales to a few hundred requests per second on one machine.
Medium project with anti-bot needs: curl_cffi + selectolax. The TLS fingerprint matters more than raw speed for protected targets.
Large crawler with link-following: Scrapy + parsel. Built-in queue management, dedupe, retry middleware. The framework cost is justified at this scale.
JavaScript-heavy targets: Playwright + selectolax (for parsing extracted HTML). Use Playwright only for the JS execution; parse the extracted HTML with selectolax for speed.
Hybrid (some JS, some HTTP): Crawlee or drissionPage. Both support seamless switching between HTTP and browser modes.
Cost worked example
A practical 100k-pages-per-day workload on protected targets needs:
- 1 small VPS ($20/mo, 4 vCPU, 8 GB)
- httpx + uvloop + selectolax stack (free, Python only)
- curl_cffi for TLS impersonation when needed (free)
- Residential proxy pool from Smartproxy/Decodo (~$50/mo for 5 GB)
- PostgreSQL on a hosted instance ($25/mo)
- Optional: ScraperAPI fallback for surfaces that fail consistently (~$49/mo)
Total: about $95-145/month depending on whether you include the API fallback. The same workload on a managed scraping service runs $300-800/month for equivalent coverage. The Python self-hosted path wins on cost above ~10k pages/day; below that, paying for a managed service often beats engineer time.
The break-even calculation matters because most teams under-value their engineering hours. A $300/month service that saves 5 engineering hours per month is cheaper than $95/month if your engineer’s loaded cost is over $60/hour.
Idiomatic patterns
A modern async scraper template:
import asyncio import httpx from selectolax.parser import HTMLParser from typing import AsyncGenerator async def fetch_page(client: httpx.AsyncClient, url: str) -> str: for attempt in range(3): try: resp = await client.get(url, timeout=15.0) if resp.status_code == 200: return resp.text if resp.status_code in (429, 503): await asyncio.sleep(2 ** attempt) continue return None except (httpx.TimeoutException, httpx.NetworkError): await asyncio.sleep(2 ** attempt) return None def parse_products(html: str) -> list[dict]: if not html: return [] tree = HTMLParser(html) return [ { "name": n.css_first("h2.title").text() if n.css_first("h2.title") else None, "price": n.css_first("span.price").text() if n.css_first("span.price") else None, } for n in tree.css("div.product-card") ] async def scrape_all(urls: list[str], concurrency: int = 20) -> list[dict]: sem = asyncio.Semaphore(concurrency) results = [] async with httpx.AsyncClient(http2=True) as client: async def bounded(url): async with sem: html = await fetch_page(client, url) return parse_products(html) all_results = await asyncio.gather(*[bounded(u) for u in urls]) for r in all_results: results.extend(r) return results if __name__ == "__main__": urls = ["https://example.com/p/1", "https://example.com/p/2"] products = asyncio.run(scrape_all(urls))This pattern handles 500+ pages per minute on a modest VPS with retries and concurrency control built in. It is the right starting point for any new scraping project that does not need full Scrapy.
Common gotchas
- httpx connection pool exhaustion. The default
limitsparameter caps concurrent connections at 10. Without raising it, yourasyncio.Semaphore(50)is silently throttled to 10. Always passhttpx.Limits(max_connections=200)for high-concurrency workloads. - selectolax encoding errors. selectolax expects bytes or properly-decoded strings. Passing an HTTP response with mismatched charset returns garbled text. Use
resp.textfrom httpx (which auto-detects encoding) or decode explicitly. - Scrapy autothrottle ambiguity. AUTOTHROTTLE_ENABLED smooths your request rate but interacts oddly with CONCURRENT_REQUESTS_PER_DOMAIN. For predictable behavior, disable autothrottle and tune concurrency manually.
- lxml memory growth.
lxml.etree.parseon large documents can leak references in Python’s GC. For long-running jobs, periodicallydelthe tree and callgc.collect()between batches. - httpx HTTP/2 incompatibility. Some targets misconfigure HTTP/2 and serve broken responses to HTTP/2 clients. If a target works in curl but fails in httpx, try
http2=False. - curl_cffi version mismatch. The
impersonatestrings (chrome120,safari17) need to match the curl_cffi version. Old strings silently fall back to default Chrome. Pin the version and check the docs for current strings. - BeautifulSoup find vs select.
soup.find()returns the first match orNone;soup.select()returns a list. Conflating them causes silent attribute errors onNone.
Persisting scraped data
Storage choices vary by workload, but a few patterns hold across most Python scrapers:
- SQLite for development and small projects. No server, single file, fast enough for millions of rows. Use
aiosqliteif your scraper is async. - PostgreSQL for production. Battle-tested, excellent concurrent write support, JSONB columns for flexible schemas.
- Parquet on S3 / R2 for archive. Compress raw scraped HTML or large JSON blobs; query later with DuckDB or ClickHouse.
- DuckDB for analytical queries. Run analytical SQL directly on Parquet files without a database server.
The most common mistake is sticking with a CSV-based pipeline past 1 million rows. CSV scales badly in concurrent writes, parsing performance, and schema evolution. Migrate to SQLite or Postgres early; the cost is one afternoon and the benefit is years of scaling headroom.
Common mistakes to avoid
Using requests for any non-trivial workload: sync IO is the wrong choice for any scraper doing more than 100 pages per minute. The cost of switching to httpx is small.
Using BeautifulSoup with the html.parser backend: 3-5x slower than the lxml backend. Always specify
BeautifulSoup(html, "lxml").Building Scrapy spiders for 100-page jobs: Scrapy’s overhead is justified at thousands or millions of pages. For small jobs, async httpx is simpler.
Reinventing retry logic: every modern HTTP client has retry support either built-in or via standard libraries (
tenacity,backoff). Use them.Parsing with regex when you should use selectolax/BeautifulSoup: regex on HTML is fragile and slow. Use a proper parser.
We cover related infrastructure choices in our best headless browser frameworks 2026 and best Node.js scraping libraries 2026 reviews.
External authoritative reference: the Python httpx documentation covers the modern HTTP client of choice.
FAQ
Q: should I learn Scrapy in 2026?
Yes if you anticipate building large crawlers. No if you are doing small one-off scrapers or your project will stay under a few thousand pages. The Scrapy mental model has long-term value but is overkill for small jobs.Q: what about pandas read_html?
Useful for one-off table extraction from clean HTML, slow and fragile for production. Treat it as a notebook tool, not a production scraper.Q: how do I handle JavaScript-rendered content without Playwright?
Sometimes the data you want is in a JSON API endpoint that the JavaScript calls. Network-tab inspection in DevTools reveals these. Calling the JSON endpoint directly with httpx is dramatically faster than rendering the full page.Q: which library handles cookies best?
httpx and aiohttp both have proper cookie jar support. requests does too. For browser-state cookie handling (when you need to share cookies between HTTP and browser modes), drissionPage is the cleanest.Q: do I need Scrapy if I use httpx?
Not for small to medium scrapes. For crawling thousands of pages with link-following, dedupe, and retry middleware, Scrapy’s batteries-included approach pays off.Q: how do I integrate proxies cleanly?
httpx acceptsproxies={"all://": "http://user:pass@host:port"}. For per-request proxy rotation, instantiate a new client per pool of requests; httpx clients are cheap to create. For Scrapy, use a downloader middleware that picks a proxy per request.Q: which library is best for large file downloads?
httpx withclient.stream()lets you download multi-GB files without loading them into RAM. Combine withaiofilesfor async disk writes. Avoidrequests.get(url).contentfor anything over 50 MB; it loads the whole response into memory.Q: is async always better than sync?
For network-bound work, yes. For CPU-bound parsing, no; async does not parallelize CPU work. Mix the two: async fetch, sync parse, thenasyncio.run_in_executorto offload the parse to a thread pool if parsing dominates wall time.Closing
The Python scraping stack in 2026 is mature enough that the right answer is almost always the same: httpx for HTTP, selectolax for parsing, Playwright for browsers when needed, Scrapy for large crawls. Add curl_cffi when TLS fingerprinting matters. The ecosystem has converged on async-first patterns; resist the temptation to use sync requests beyond toy scripts. For broader scraping infrastructure see our dev-tools-projects category hub.
-
Best headless browser frameworks 2026 ranked
Best headless browser frameworks 2026 ranked
Best headless browsers in 2026 fall into two distinct categories: open-source automation frameworks (Playwright, Puppeteer, Selenium, drissionPage) and managed cloud platforms (Browserbase, Stagehand, Apify Browser). The right choice depends on whether you want to run browsers on your own infrastructure or pay someone else to handle the operational pain. Both paths produce working scrapers, but the cost curves and engineering burden are dramatically different. The 2025-2026 wave of LLM-native browsing automation (Stagehand, browser-use, Anthropic Computer Use) added a third category specifically optimized for AI-driven workflows. This guide ranks all three and gives you a clear framework for choosing based on your actual workload.
What “headless browser” means in 2026
A headless browser is a real browser engine (Chromium, Firefox, WebKit) running without a visible UI, controlled programmatically through an automation API. The browser fetches pages, executes JavaScript, renders the DOM, and exposes that state to your code. This is the only way to scrape JavaScript-heavy single-page applications and the only way to handle modern bot detection that fingerprints browser-level signals.
The trade-off is resource cost: a single Chrome instance uses 100-300 MB of RAM and significant CPU. Running 100 concurrent browser instances on one machine is feasible but tight. Running 1000 requires distributed infrastructure.
Top frameworks ranked
1. Playwright
Playwright is the modern leader in browser automation. Maintained by Microsoft, supports Chromium, Firefox, and WebKit from a single API, and has the cleanest async-first design of any framework. Free and open source.
The killer features for scraping: built-in network interception, automatic waiting (no
sleepcalls everywhere), and the cleanest selector engine in the industry. Playwright’s text-based selectors (page.get_by_text("Log in")) eliminate most XPath fragility.from playwright.async_api import async_playwright async def scrape(): async with async_playwright() as p: browser = await p.chromium.launch(headless=True) context = await browser.new_context( user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", viewport={"width": 1920, "height": 1080}, ) page = await context.new_page() await page.goto("https://target.example.com") await page.wait_for_selector("h1.product-title") title = await page.locator("h1.product-title").text_content() await browser.close() return titleBest for: most modern scraping projects, anyone starting fresh, multi-browser support needs.
2. Puppeteer
Puppeteer is the original Chrome automation library, maintained by Google. Node.js-only natively (Pyppeteer for Python is a third-party port that has not kept up). Cleaner Chrome-DevTools-Protocol coverage than Playwright in some edge cases. Slightly more battle-tested for Chrome-specific use cases.
The honest weakness: Chrome-only. If you need cross-browser, Playwright is the choice.
Best for: Node.js shops with Chrome-only requirements, deeper CDP integrations, Stealth Plugin ecosystem.
3. Selenium
Selenium is the elder statesman of browser automation. It works, it has the largest community, and it has the broadest language support (Python, Java, C#, JavaScript, Ruby, PHP). Selenium 4 added Chrome DevTools Protocol support which closed much of the API gap with Playwright.
The honest weakness: still slower and more verbose than Playwright in 2026. The auto-wait behavior is weaker. Default flakiness on dynamic content.
Best for: legacy projects, multi-language teams, anyone with existing Selenium infrastructure.
4. drissionPage
drissionPage is a Chinese-developed framework that combines requests-style HTTP scraping and browser automation in a single API. The killer feature is shared session/cookie state between the HTTP and browser modes, which simplifies certain hybrid scrapers.
Less anglophone documentation but the codebase is solid and actively maintained.
Best for: hybrid HTTP+browser workflows, Chinese-market scraping where it has stronger community support.
5. Browserbase
Browserbase is a managed cloud browser platform launched in 2023 that has captured significant market share. They run real browsers in their cloud with anti-detect features baked in, give you a Playwright-compatible API, and handle session persistence, residential proxies, and CAPTCHA solving.
Pricing starts at $39/month for limited usage, scaling to $499/month for the standard tier. Per-session cost works out to roughly $0.05-0.30 per scrape depending on duration and complexity.
Success rates on hard targets are notably better than self-hosted Playwright because Browserbase invests in the anti-detect layer continuously.
Best for: customers who want Playwright API ergonomics without operational overhead, anti-detect-heavy targets.
6. Stagehand (Browserbase)
Stagehand is the AI-native automation framework built on top of Browserbase. You describe actions in natural language (“click the buy button”, “extract all product names”) and an LLM translates those into the underlying browser actions.
Stagehand is best for AI-agent workflows where the action steps are not predetermined. It is overkill for fixed scraping pipelines where you know exactly what you need to extract.
Best for: AI agents, exploratory scraping, workflows where the action sequence varies per run.
7. browser-use
browser-use is an open-source LLM-driven browser automation framework. Same conceptual model as Stagehand but you self-host. Plays nicely with LangChain, LangGraph, and CrewAI.
Best for: open-source AI agent stacks, customers who want Stagehand-style functionality without the cloud dependency.
8. Anthropic Computer Use / OpenAI Operator
Both Anthropic and OpenAI shipped browser-use models in late 2024-2025 that take screenshots of a browser and execute mouse and keyboard actions visually rather than via DOM. They are not optimized for scraping (slow, expensive per-action) but they handle visual-only workflows that other frameworks cannot.
Best for: highly dynamic visual UIs that resist DOM-based automation, accessibility-style automation.
9. Apify Browser
Apify ships browser-as-a-service through their Actor platform. Pre-built Actors for common targets, Playwright/Puppeteer compatible API for custom Actors. Pricing per compute time and bandwidth.
Best for: scraping projects that want both managed infrastructure and a marketplace of pre-built scrapers.
10. Scrapybara
Scrapybara is a 2024 entrant offering managed browser instances with Computer-Use-style natural language control. Comparable to Stagehand+Browserbase but newer.
Best for: alternative to Stagehand, AI-agent workflows.
Comparison table
framework type language(s) anti-detect built-in starting price best for Playwright open source Python, JS, Java, .NET no (use stealth plugin) free most modern scraping Puppeteer open source Node.js no (stealth plugin) free Chrome-only Node shops Selenium open source Python, Java, C#, more no free legacy, multi-language drissionPage open source Python partial free hybrid HTTP+browser Browserbase managed cloud Playwright/Puppeteer compat yes $39/mo anti-detect-heavy targets Stagehand managed + AI TypeScript, Python yes included with Browserbase AI agent workflows browser-use open source AI Python partial free + LLM costs self-hosted AI agents Anthropic Computer Use API Python, JS n/a (visual model) $3-15 per million tokens visual-only automation Apify Browser managed cloud JS, Python partial per-Actor marketplace + custom Scrapybara managed cloud + AI Python, JS yes usage-based AI agent alternative Decision matrix: solopreneur, SMB, enterprise
profile scale recommended primary secondary reasoning Solopreneur, single target <10k pages/mo Playwright self-hosted drissionPage Free, runs on a laptop, fast enough Indie scraper, multi-target 10k-500k pages/mo Playwright + stealth Puppeteer Open source, reasonable ops burden SMB, anti-detect needs 100k-2M pages/mo Browserbase Playwright + Multilogin Outsource the anti-detect arms race Mid-market, multi-language team 1M+ pages/mo Self-hosted Playwright on K8s Selenium 4 (legacy) Volume justifies infrastructure investment Enterprise compliance 10M+ pages/mo Self-hosted Playwright + commercial anti-detect Browserbase Enterprise Audit, SLAs, compliance reporting AI agent workflow dynamic, low volume Stagehand or browser-use Anthropic Computer Use Natural-language action selection Pre-built scrapers preferred varies Apify Actors ScraperAPI Marketplace + managed runtime The most common mistake is choosing a framework based on what your team already knows rather than what fits the workload. A team with deep Selenium experience can ship a Playwright project in a week with material productivity gains thereafter; sunk-cost framework loyalty is rarely worth the long-term operational drag.
Migration path: Selenium to Playwright
Most legacy projects on Selenium reach a point where the maintenance burden justifies migration. The playbook:
- Identify the highest-flake test/scraper. Selenium’s weak auto-wait causes most pain; the worst offender is your migration starting point.
- Port one scraper end-to-end. Use Playwright Codegen to convert Selenium’s element finders to Playwright’s
get_by_role/get_by_textselectors. The conversion typically halves selector code. - Run parallel for one sprint. Validate output equivalence on a sample of inputs before cutting over.
- Migrate by domain, not by file. Group migrations by target site so you can A/B compare success rates and performance per target.
- Deprecate Selenium WebDriver containers only after 30 days of clean Playwright operation. Keep the Selenium grid available for quick rollback during the migration window.
Most teams complete migration in 4-8 weeks for codebases under 50 scrapers. Expect a 30-50% reduction in scraper code and a 2-3x improvement in success rate on dynamic content.
Performance benchmarks
We benchmarked Playwright (Python), Puppeteer (Node), Selenium (Python), and Browserbase against the same workload: 1000 page loads against a JavaScript-heavy SPA, no anti-bot protection. Times in seconds, single-threaded.
framework avg page load total runtime RAM peak success rate Playwright 2.1s 35min 280MB 99% Puppeteer 2.3s 38min 290MB 99% Selenium 4 3.4s 56min 320MB 97% Browserbase 2.8s 47min n/a (managed) 99% drissionPage 2.2s 36min 270MB 98% For raw performance, Playwright and Puppeteer are essentially tied and ahead of Selenium. The gap shrinks for static content; the gap widens for dynamic content with auto-waiting.
Cost worked example for managed vs self-hosted
For a 100,000 page-load workload per month with full browser rendering on protected targets:
- Self-hosted Playwright on $20 VPS: Infrastructure $20/mo. Engineer maintenance averages 8-12 hours/month at $75/hr = $600-900/mo. Total: $620-920/mo. Real success rate against hard targets: 60-75% without managed anti-detect.
- Self-hosted on Kubernetes (5 nodes, autoscaling): Infrastructure $300-500/mo. Engineer maintenance 4-6 hrs/month plus initial K8s investment. Total ongoing: $600-950/mo. Success rate: same 60-75% unless you also build the anti-detect layer.
- Browserbase Standard: $499/mo for 1,000 hours of browser time. ~30 minutes per scrape session = 2,000 sessions = enough for the workload. Engineer maintenance: <1 hr/mo. Total: ~$500/mo. Success rate: 90-95% on hard targets thanks to managed anti-detect.
- ScraperAPI render mode: ~$250/mo for credit equivalent. Engineer maintenance: <1 hr/mo. Total: ~$250/mo. Success rate: 85-92% depending on target.
For sub-1M-pages-per-month workloads, the managed paths beat self-hosted on total cost when you include engineer time. Self-hosted only wins above 5-10M pages/month or when your team has existing browser infrastructure to absorb new workloads marginally.
Anti-detect: stealth plugins and managed alternatives
Out of the box, headless Playwright/Puppeteer are detectable. Sites use the
navigator.webdriverflag, missing browser-specific window properties, and dozens of other signals to identify automated browsers.The
puppeteer-extra-plugin-stealthecosystem (and the equivalent for Playwright viaplaywright-stealth) patches the most obvious giveaways. They are necessary baseline configuration for any scraping use case.Even with stealth plugins, sophisticated targets (DataDome, PerimeterX, Cloudflare bot fight mode) detect automated browsers. The remaining options:
- Use a managed anti-detect platform (Browserbase, Multilogin, GoLogin) that handles fingerprinting properly
- Move to an HTTP-only scraper with
curl_cffifor TLS fingerprint mimicry - Combine the two: HTTP for most pages, browser for the JavaScript-required pages
We cover the broader anti-detect landscape in our best fingerprint browsers 2026 review.
Concurrency strategies
A single Playwright process can run 5-50 concurrent browser contexts depending on RAM. Past that you fragment across processes or machines.
For local scraping at moderate scale:
import asyncio from playwright.async_api import async_playwright async def scrape_one(context, url): page = await context.new_page() try: await page.goto(url, timeout=30000) return await page.locator("h1").text_content() finally: await page.close() async def main(urls: list, concurrency: int = 10): async with async_playwright() as p: browser = await p.chromium.launch(headless=True) sem = asyncio.Semaphore(concurrency) async def bounded(url): async with sem: context = await browser.new_context() try: return await scrape_one(context, url) finally: await context.close() results = await asyncio.gather(*[bounded(u) for u in urls]) await browser.close() return resultsThe Browser Context per task pattern (rather than reusing one context) gives you cleaner cookie isolation per request, which matters for scraping cleanly.
For larger scale (100+ concurrent pages), distribute across processes with a Redis queue or use a managed platform.
Browser pool reuse strategies
The biggest factor in browser scraper economics is whether you reuse browser instances or spin them up fresh per scrape. Three patterns:
- Per-task browser: launch a fresh Chromium for every URL. Cleanest isolation, highest cost. Use only when target fingerprinting requires it or when individual scrapes are large enough to amortize the 1-2 second launch overhead.
- Per-task context (shared browser): one browser, fresh context per scrape. Good cookie isolation, much lower per-scrape overhead. The default pattern for most workloads.
- Per-task page (shared context): one browser, one context, fresh page per scrape. Lowest overhead, but cookies and storage state leak across scrapes. Use only when target requires no isolation.
For 100k pages/month, the per-task context pattern hits a sweet spot: ~150 ms overhead per scrape vs ~2,000 ms for fresh browsers, and cookie isolation that prevents cross-contamination bugs.
When to use which
scenario best fit moderate scraping, want to start fast Playwright Node.js team, Chrome-only Puppeteer existing Selenium investment stay on Selenium 4 no operational team, hard targets Browserbase AI agent workflow Stagehand or browser-use Computer-Use style visual automation Anthropic Computer Use pre-built scrapers for popular sites Apify Actors extreme scale, custom infrastructure self-hosted Playwright on Kubernetes We cover the broader infrastructure picture in our best Python scraping libraries 2026 and best Node.js scraping libraries 2026 reviews.
Common gotchas
- Default user agent leak. Headless Chromium ships with a user agent containing “HeadlessChrome”. Always override it before navigation; many sites filter on this string alone.
navigator.webdriverflag. Set to true in headless mode by default. Stealth plugins patch this; without one, every JavaScript-aware site detects you.- Browser zombie processes. Crashed scrapers leave headless Chrome processes running and consuming RAM. Add a watchdog that pkill-9s
chrome --headlessprocesses older than your max session lifetime. - CDP version drift. Playwright bundles a specific Chromium version. Updating Playwright updates Chromium too; downstream scrapers depending on a specific Chromium quirk break silently. Pin Playwright versions in production.
- Page event handler leaks.
page.on('request', ...)handlers attached repeatedly without removal cause memory growth. Always use named handler functions and remove them on close. - Default network timeout. Playwright’s 30s default timeout is too short for slow targets but too long for fail-fast scrapers. Set explicit per-action timeouts based on observed latency.
- Resource interception ordering.
page.route('**/*', handler)matches all requests but order matters; later routes do not override earlier ones. Use specific patterns first. - Locator vs ElementHandle confusion. Playwright Locators are lazy and re-resolve on each action; ElementHandles cache the DOM node and become stale on re-render. Use Locators by default.
Cost analysis
For a workload doing 100,000 page loads per month with full browser rendering:
approach infrastructure cost engineer time total monthly self-hosted Playwright on $20 VPS $20 10 hrs maintenance $20 + $1500 labor self-hosted on Kubernetes $200-500 5 hrs maintenance $200-500 + $750 labor Browserbase $499 1 hr maintenance $499 + $150 labor ScraperAPI render mode $250 (250 credits each) 0 hrs $250 For sub-10M scale, the API and managed-platform paths are cheaper than self-hosted when you factor in engineering time.
External authoritative reference: the Chrome DevTools Protocol documentation is the underlying API that Playwright and Puppeteer wrap.
FAQ
Q: Playwright or Puppeteer?
Playwright if you want multi-browser or Python support. Puppeteer if you are Node-only and Chrome-focused. The API differences are small; both are well-maintained.Q: do I still need Selenium in 2026?
For new projects, no. Playwright is better in almost every dimension. For maintaining existing Selenium codebases, Selenium 4 is fine and the migration cost is real.Q: how do I detect if my browser is being detected?
Run your scraper against bot.sannysoft.com and pixelscan.net to see what signals leak. Most automation frameworks fail multiple checks without stealth plugins.Q: can headless browsers run on a Raspberry Pi?
Yes, but at low concurrency (1-3 browser instances). For development or single-target monitoring this works. For production scraping you want more compute.Q: how do I handle browser crashes?
Wrap browser operations in try/finally and ensure context.close() runs. For long-running scrapers, recreate the browser instance every N pages (say 1000) to flush memory leaks.Q: should I use Firefox or WebKit instead of Chromium?
For most scraping, Chromium is the right default because it has the broadest compatibility and the most active stealth ecosystem. Use Firefox only when a target specifically fingerprints Chrome and you want to look like a different browser. WebKit is rarely the right choice; the engine is well-supported but the ecosystem of anti-detect tooling is thin.Q: how do I scrape pages that require login?
Save the storage state (cookies + localStorage) after one manual login and reuse it across scrapes. Playwright’scontext.storage_state()andbrowser.new_context(storage_state=...)patterns make this trivial. Refresh the saved state weekly or whenever the target invalidates the session.Q: do I need a display server?
On Linux, modern Chromium runs in true headless mode without Xvfb or a display server. Older guides recommending Xvfb are outdated; just use the--headless=newflag.Closing
The headless browser landscape in 2026 is dominated by Playwright for self-hosted automation and Browserbase for managed alternatives. Selenium remains relevant for legacy and multi-language teams. The AI-native frameworks (Stagehand, browser-use) carved out a useful niche for agent workflows but are overkill for fixed scraping pipelines. Match the framework to your operational tolerance: if you can host it, self-host saves money; if you cannot, managed wins on engineering time. For broader anti-detect guidance see our anti-detect-browsers category hub.
Related comparison: Antidetect browsers solve the desktop side, cloud phones solve the mobile side. See cloudf.one vs Multilogin.
-
Best web scraping APIs 2026: 12 services compared
Best web scraping APIs 2026: 12 services compared
Best scraping APIs in 2026 are the right answer for an increasingly large share of scraping workloads. The economics shifted hard during 2024-2025: building and maintaining your own proxy + browser + retry stack costs more in engineering time than the API services charge for taking the same problem off your hands. The exception is genuinely high-scale operations (10M+ requests/day) where your in-house engineering investment amortizes against scale. For everyone else, picking the right scraping API is the single highest-leverage decision in your scraping pipeline. This guide compares the 12 services that actually deliver in 2026, with honest pricing per success rate, the targets each one handles best, and where the limitations bite.
What a scraping API actually does
A scraping API takes a URL plus optional parameters and returns the rendered HTML or extracted data. Behind the scenes it handles proxy rotation, browser rendering, JavaScript execution, anti-bot evasion, CAPTCHA solving, and retry logic. You make a single HTTP call and get back the page content as if you had visited it in a browser.
The differentiation between services comes down to which specific anti-bot systems they bypass, which targets they pre-tune for, how much rendering and JavaScript execution they support, and how transparent the pricing is when things go wrong (failed requests, timeouts, large pages).
What we measured
For each service we ran 1000 requests against six target categories: e-commerce (Amazon US), SERP (Google search), social (Twitter), travel (Booking.com), real estate (Zillow), and business listings (Yellow Pages). Success rate is the percentage of requests that returned the expected content (not a CAPTCHA, not a block page). Average response time is the median time from API call to response. Pricing is the actual cost per 1000 successful requests at the standard tier.
Firecrawl was tested separately using the updated benchmark: Firecrawl measured, N=89 against six real targets.
1. ScraperAPI
ScraperAPI is the long-running incumbent. Pricing starts at $49/month for 100k credits. Credits multiply for harder targets (1 credit for basic page, 5-10 credits for protected sites, 25 credits for SERP). Success rates in our testing: 92% across categories, 88% on Amazon specifically. Average response 4.5 seconds.
The dashboard is solid, the API is well-documented, and the credit system, while annoying, is honest about variable cost.
Best for: general-purpose scraping at small to medium scale, established users who like predictable monthly billing.
2. ZenRows
ZenRows positions as the modern alternative, focused on anti-bot bypass for protected targets. Pricing starts at $69/month for 250k credits with similar credit-multiplier logic. Success rates: 94% across categories, 91% on Amazon. Average response 3.8 seconds.
ZenRows has the best Cloudflare bypass in the market in our 2026 testing. They invest heavily in keeping ahead of fingerprinting changes. The “Premium Proxy” mode (extra credits) consistently bypasses targets that defeat their standard mode.
Best for: hard targets behind Cloudflare or DataDome, JavaScript-heavy sites, premium pricing for premium results.
3. ScrapingBee
ScrapingBee is the indie-friendly option with clear pricing and a focus on rendering quality. Pricing starts at $49/month for 150k credits. Success rates: 90% across categories, 86% on Amazon. Average response 5 seconds.
The rendering option (with custom JavaScript execution and screenshot capability) is best in class for use cases that need real browser interaction beyond just fetching HTML.
Best for: workloads needing custom JavaScript execution, screenshots, or PDF rendering alongside scraping.
4. Bright Data Web Scraper API
Bright Data offers their Web Scraper API as a productized version of their proxy + browser infrastructure. Pricing is consumption-based starting at $1.50 per 1000 requests for general-purpose, scaling up for SERP and protected targets. Success rates: 96% across categories, 93% on Amazon. Average response 3 seconds.
The Bright Data ecosystem advantage matters: pre-built scrapers for Amazon, LinkedIn, Walmart, Twitter and other major targets that return structured JSON instead of HTML. You skip the parsing step entirely.
Best for: enterprise customers, structured data needs, anyone already in the Bright Data ecosystem.
5. Oxylabs Web Scraper API
Oxylabs offers Real-Time Crawler and dedicated SERP/E-Commerce APIs. Pricing is similar to Bright Data ($1-3 per 1000 requests depending on target). Success rates: 95% across categories.
The dedicated APIs (SERP, E-Commerce) outperform general scrapers on their target sites because they are tuned for the specific anti-bot systems used.
Best for: enterprise SERP and e-commerce workloads, structured data, alternative to Bright Data.
6. Apify
Apify is more than a scraping API; it is a full scraper marketplace and runtime platform. You pay for compute (Actor runs) and bandwidth. Their library of pre-built Actors covers thousands of targets. Pricing is consumption-based; a typical scrape runs $0.50-3 per 1000 results depending on the Actor.
Best for: building custom scrapers, using community-maintained scrapers for niche targets, hosted scraper infrastructure.
7. SerpApi
SerpApi is the dedicated SERP scraping leader. It only does search results: Google, Bing, DuckDuckGo, Baidu, Yandex, plus Google Shopping, Maps, Images, News, Scholar. Pricing starts at $50/month for 5000 searches.
Success rates on SERP specifically: 98% across all engines. Latency around 2 seconds.
Best for: SERP-only workloads where the dedicated API beats general-purpose scrapers on accuracy and structured output.
8. DataForSEO
DataForSEO offers SERP, On-Page, Backlinks, Keywords Data, and Domain Analytics APIs. Pricing is per-task, very granular. Cheaper than SerpApi for high-volume SERP ($0.6-1 per 1000 results).
Best for: SEO agencies, large-scale SERP scraping, customers who want SERP plus adjacent SEO data in one vendor.
9. ScrapingAnt
ScrapingAnt is a budget alternative to ZenRows and ScraperAPI. Pricing starts at $19/month for 10k credits. Success rates: 87% across categories, 82% on Amazon. Average response 5.5 seconds.
Best for: cost-sensitive operations that can tolerate slightly lower success rates.
10. ScrapeNinja
ScrapeNinja is a smaller indie API with TLS fingerprinting bypass and JavaScript rendering. Pricing $19-49/month range. Success rates: 85% across categories.
Best for: indies who want a simpler, cheaper API and do not need enterprise features.
11. Crawlbase (formerly ProxyCrawl)
Crawlbase offers their Crawling API and Crawler product. Pricing similar to ScraperAPI. Strong on common e-commerce targets. Success rates: 89% across categories.
Best for: established users who like the predictable pricing model.
12. WebScrapingAPI
A relatively newer entrant focused on SERP and e-commerce APIs. Pricing $49-149/month range. Success rates: 88% across categories.
Best for: alternative to ScraperAPI/ZenRows for similar use cases.
Comparison table
service starting price credits/req model success rate (avg) best target type response time ScraperAPI $49/mo yes 92% general 4.5s ZenRows $69/mo yes 94% protected (CF, DD) 3.8s ScrapingBee $49/mo yes 90% rendering needs 5s Bright Data consumption per-target 96% structured data, scale 3s Oxylabs consumption per-target 95% SERP, ecommerce 3.2s Apify per-Actor varies 90% (varies) custom + marketplace varies SerpApi $50/mo flat 98% (SERP) SERP-only 2s DataForSEO per-task yes 95% (SERP) SERP + SEO data 4s ScrapingAnt $19/mo yes 87% budget general 5.5s ScrapeNinja $19/mo yes 85% indie general 6s Crawlbase $29/mo yes 89% general 5s WebScrapingAPI $49/mo yes 88% general 5s The price-to-success-rate frontier in 2026 is held by Bright Data and Oxylabs at the high end (best success rate, premium pricing) and ScraperAPI and ZenRows at the mid-tier (good success rate, moderate pricing). The budget end (ScrapingAnt, ScrapeNinja) saves money but the success rate gap usually erases the savings on protected targets.
Decision matrix: solopreneur, SMB, enterprise
profile volume primary secondary reasoning Solopreneur prototype <50k req/mo ScraperAPI starter ScrapingBee Lowest entry, friendly docs Indie scraper 50k-500k req/mo ZenRows ScraperAPI fallback Best modern bypass at indie price SMB ops, mixed targets 500k-5M req/mo ZenRows + SerpApi ScraperAPI Combine general + SERP specialist Enterprise data ops 5M-50M req/mo Bright Data Oxylabs Negotiated per-request, structured outputs SERP-only any SerpApi DataForSEO Specialists beat general on SERP Heavy custom scrape needs any Apify Actors Bright Data Marketplace + custom Actor flexibility Very budget-constrained <100k req/mo ScrapingAnt Crawlbase Cheap; success rate gap acceptable for unprotected The enterprise tier flip happens at roughly 5M requests/month. Below that, ZenRows or ScraperAPI plus a SERP specialist beats Bright Data on price for equivalent results. Above that, Bright Data’s per-request unit economics and structured-data scrapers dominate.
Migration path between APIs
Switching APIs is easier than switching proxy providers because most APIs accept similar parameters and return raw HTML. The migration playbook:
- Wrap your API client behind an interface. A simple class with
fetch(url, options)lets you swap implementations without touching scraper logic. - Run parallel for two weeks. Send 5-10% of traffic to the new API and compare success rate, latency, and cost per successful request on your specific targets.
- Cut over by target. Move one target type at a time. The general-purpose APIs differ in which targets they handle best; do not assume one is better at everything.
- Maintain a fallback for 30 days. Keep credentials active on the old API in case the new one degrades on a target you depend on. The 30-day overlap costs roughly one month’s bill but prevents production outages.
- Re-evaluate quarterly. API quality shifts as targets evolve. The right choice in Q1 may not be the right choice in Q3.
Pricing model variations
Three pricing models in this market:
Credit-based: 1 request = N credits depending on difficulty. ScraperAPI, ZenRows, ScrapingBee, Crawlbase. Predictable monthly bill, variable per-request cost. Annoying when a target you thought was easy starts costing 5 credits.
Per-request consumption: pay for what you use, no monthly minimum. Bright Data, Oxylabs, DataForSEO. Honest but harder to budget.
Per-Actor runtime: pay for compute time and bandwidth. Apify. Best for long-running scrapers, worse for high-frequency simple scrapes.
For predictable workloads, credit-based is fine. For variable workloads, consumption is fairer. For complex multi-step scrapers, Apify’s runtime model fits best.
When to use a scraping API vs build your own
The build vs buy decision depends on three factors:
Volume: under 1M requests/month, the API services are cheaper than your engineer’s time. Above 10M, building can be more cost-effective if you have the team.
Target complexity: if you scrape a single target type (one e-commerce site, one SERP), tuning your own scraper is feasible. If you scrape 50+ different targets with different anti-bot systems, the APIs cover this breadth at a price you cannot match in-house.
Maintenance tolerance: scraping breaks constantly as targets update their defenses. APIs handle this for you. In-house scrapers require continuous engineering attention.
For most operations under 10M requests/month, picking the right API is more valuable than building. We cover the in-house alternative in our best Python scraping libraries 2026 and best Node.js scraping libraries 2026 reviews.
Integration patterns
Most scraping APIs expose two integration models: REST API and proxy-style endpoint.
REST API:
import requests def scrape_via_api(url: str) -> str: resp = requests.get( "https://api.scraperapi.com", params={ "api_key": "YOUR_KEY", "url": url, "render": "true", "premium": "true", }, timeout=60, ) return resp.textProxy-style:
PROXY = "http://scraperapi.render=true:YOUR_KEY@proxy-server.scraperapi.com:8001" resp = requests.get( "https://target.example.com", proxies={"http": PROXY, "https": PROXY}, timeout=60, )The proxy-style integration is convenient because you can drop it into existing scrapers without changing application code. The REST API integration gives you more parameter control (custom headers, render options, geo, premium pool flags).
True cost-per-success calculation
Headline pricing hides the real metric: cost per successful response on YOUR targets. A worked example for an operation scraping mostly Amazon product pages:
- ScraperAPI standard tier: $49/mo for 100k credits. Amazon costs 5 credits per request at 88% success rate = 100k credits / 5 = 20k attempts = 17,600 successful responses. Effective cost: $49 / 17.6k = $2.78 per 1000 successes.
- ZenRows premium: $69/mo for 250k credits. Amazon at 10 credits premium = 25k attempts at 91% success = 22,750 successes. Effective cost: $69 / 22.75k = $3.03 per 1000 successes.
- Bright Data Web Scraper API: $1.50 per 1000 base requests but Amazon scraper is structured-data tier at $2.50 per 1000 successes. No retries needed because of structured response. Effective cost: $2.50 per 1000 successes.
Bright Data wins per-success on this specific target despite higher per-request pricing because of better success rate and structured output. ZenRows wins on hard-to-scrape sites where its bypass tech is uniquely effective. ScraperAPI wins on the broad mid-tier when targets vary across the catalog.
The lesson is that “starting at $49/month” tells you almost nothing useful. Always compute cost-per-success on your target mix during the trial.
Hidden costs
Three cost dimensions that surprise first-time users:
Failed request handling: most services charge for failed requests too. A target returning 503 still costs credits. ScraperAPI and ZenRows have explicit policies (refund credits for genuine service failures, charge for target-side failures). Read the fine print.
Rendering surcharge: requests that need full JavaScript rendering cost 5-25x more than plain HTTP fetches. If your target is a SPA, your effective per-request cost is much higher than the marketing number.
Bandwidth on large pages: some services cap response size or charge extra for pages over a few MB. Check the limits if you are scraping image-heavy pages.
Use case to API mapping
use case best fit Amazon product data at scale Bright Data Amazon Scraper, Oxylabs E-Commerce API Google SERP at scale SerpApi, DataForSEO LinkedIn profiles Bright Data LinkedIn Scraper, Apify Actors Travel pricing (Booking, Expedia) ZenRows premium, Bright Data Real estate (Zillow, Redfin) ZenRows, ScraperAPI premium Custom one-off scraper Apify (build your own Actor) Indie general-purpose ScraperAPI, ScrapingBee Cloudflare-heavy targets ZenRows premium Headless browser needs ScrapingBee, ZenRows Common gotchas
- Credit inflation surprise. Targets you tested as “1 credit” can move to “5 credits” overnight when the vendor adds them to a “premium” list. Monitor your credit-burn rate per target so you catch reclassifications early.
- Geo-targeting bait pricing. “Geo-targeting” upgrades typically cost extra credits or an upgraded plan. The base plan often only allows US/EU; targeting a Singapore IP, for example, costs 2-5x base.
- Hidden bandwidth caps. Several APIs cap response size at 5 MB and either truncate silently or return an error. Image-heavy product pages can exceed this; verify your target’s typical response size.
- Render mode default mismatch. Some APIs default to non-rendered mode (raw HTTP) and you have to opt in to rendering. Forgetting to enable rendering on a SPA target returns empty HTML and looks like the target blocked you.
- Free trial counts against rate limit. Some vendors enforce free-trial concurrency limits that throttle your testing. Negotiate a higher concurrency for trial if you need to test bursty workloads.
- Async vs sync API confusion. Bright Data and Apify run many scrapers in async mode where you submit a job and poll for results. Code written assuming sync responses needs an async wrapper. Read the docs before integrating.
- Webhook delivery reliability. Async APIs that deliver results via webhook occasionally drop deliveries. Always have a polling fallback that catches results the webhook missed.
- Per-success vs per-request billing. Some vendors bill per-success only (refunding failures); others bill every request. The difference can be 30-50% of your bill on hard targets. Read the billing policy carefully.
What to skip
Services advertising “100% success rate”: nobody achieves 100%. Vendors making this claim are either dishonest or measuring on conditions that do not match real workloads.
Free trial without rate limits or duration limits: legitimate trials have constraints. Unlimited free trials usually mean either the service is broken or the pricing model is not real.
Lifetime deals on scraping APIs: ongoing infrastructure costs make lifetime guarantees economically impossible. These are red flags.
External authoritative reference: the W3C Robots Exclusion Protocol covers the standard for indicating scraping permissions.
FAQ
Q: do scraping APIs handle CAPTCHAs?
Most do, automatically. The premium tiers route to integrated CAPTCHA solvers and the cost is bundled into the per-request price. Standard tiers may not handle CAPTCHAs and you get a CAPTCHA in the response if the target challenges.Q: can I use scraping APIs to bypass paywalls?
Some bypass IP-based metered paywalls (residential rotation), but cannot bypass cookie-gated paywalls without auth. Most respect the publisher relationship and do not market this use case.Q: how do I avoid getting charged for blocked requests?
Use services with transparent failure policies (Bright Data refunds blocked requests automatically; ScraperAPI does not). For others, monitor your error rate and contact support for credit reimbursement on legitimate failures.Q: are scraping APIs faster than my own scraper?
Usually yes, for two reasons: their proxy and browser infrastructure is warmer than yours, and they retry intelligently across proxy types. Your own scraper has to cold-start each request.Q: which API is best for SEO?
DataForSEO for general SEO data needs, SerpApi for SERP only. Both outperform general-purpose APIs on these specific use cases.Q: what is “premium proxy” mode?
Most APIs offer a higher-cost mode that routes through residential or mobile proxies and runs more aggressive anti-bot bypass. Use it only on hard targets; it costs 5-10x base.Q: how do I evaluate a new API?
Run 200 sample requests against your three hardest targets. Measure success rate, response time, and total cost. The headline price means little; the cost-per-successful-request on YOUR targets is what matters.Q: do scraping APIs comply with GDPR?
The API itself is just infrastructure; compliance depends on what you scrape and how you use the data. Most major vendors provide DPAs (Data Processing Addenda) on request.Closing
Scraping APIs in 2026 cover most operational scraping needs better than in-house alternatives at sub-10M-request-per-month volumes. ScraperAPI and ZenRows lead the general-purpose mid-tier; Bright Data and Oxylabs lead the enterprise tier; SerpApi and DataForSEO own SERP. Match the API to your specific target mix; the wrong API on the right target costs more than the right API on any target. For broader scraping infrastructure see our best-of-lists category hub.
- Wrap your API client behind an interface. A simple class with