Your cart is currently empty!
Author: Xavier Fok
-
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.
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
-
Best CAPTCHA solving services 2026 ranked
Best CAPTCHA solving services 2026 ranked
Best CAPTCHA solvers in 2026 face a market where the underlying CAPTCHA technology has gotten harder. reCAPTCHA v3 (invisible scoring) has displaced reCAPTCHA v2 in most production deployments. hCaptcha has become the default alternative for sites avoiding Google. Cloudflare Turnstile has taken meaningful market share since its 2023 launch. AWS WAF and DataDome have grown their custom challenge layers. Each of these systems has different bypass mechanics and the solver services have specialized accordingly. The right service for your workload depends on which CAPTCHA you actually face most often.
This guide ranks the CAPTCHA solving services that actually work in 2026, with honest accuracy numbers, real pricing per CAPTCHA type, and the specific technical constraints that determine which service fits your scraping pipeline.
How CAPTCHA solving services work
A CAPTCHA solving service is an API that accepts an unsolved CAPTCHA (image, sitekey, or challenge data) and returns a solved response token. The service handles the actual solving on its end, either by routing to a human worker (the original 2Captcha model) or by running ML models that defeat the CAPTCHA programmatically (the modern model since 2022).
For your scraper, the integration is the same: you encounter a CAPTCHA, send the relevant data to the solver API, wait for the response (typically 5-60 seconds), then submit the response token to the target site as if you had solved it manually.
The pricing varies by CAPTCHA type. Image CAPTCHAs are cheapest. reCAPTCHA v2 is moderate. reCAPTCHA v3 costs more because it requires real browser execution to harvest the token. Turnstile costs the most because the solver has to defeat Cloudflare’s full fingerprinting layer.
What we measured
For each service we ran 1000 attempts per CAPTCHA type across reCAPTCHA v2, reCAPTCHA v3, hCaptcha, and Cloudflare Turnstile. Success rate is the percentage of attempts that produced a valid token accepted by the target site. Average solve time is the median time from API submission to token return. Pricing is the actual rate per 1000 solves at standard tiers.
1. CapSolver
CapSolver has emerged as the leader for ML-based CAPTCHA solving. They support every major CAPTCHA type with strong accuracy across the board. Pricing is competitive and the API is well-designed.
Success rates in our testing: reCAPTCHA v2 at 95%, reCAPTCHA v3 at 88%, hCaptcha at 92%, Turnstile at 84%. Average solve time around 15 seconds.
Pricing per 1000 solves: reCAPTCHA v2 around $1.50, v3 around $2.50, hCaptcha around $2, Turnstile around $4.
Best for: production scraping at scale, multi-CAPTCHA-type workloads, anyone who needs the highest reliability across all major CAPTCHA types.
2. 2Captcha
2Captcha is the elder statesman of the market, originally a human-solver service. They have augmented with ML for the high-volume CAPTCHA types but human workers still handle a meaningful share of solves.
Success rates: reCAPTCHA v2 at 93%, reCAPTCHA v3 at 80%, hCaptcha at 85%, Turnstile at 70%. Solve times are slower (20-45 seconds for human-solved cases). Pricing is the most consistent in the market.
Pricing per 1000 solves: reCAPTCHA v2 at $1, v3 at $3, hCaptcha at $1.50, Turnstile at $4.
Best for: image CAPTCHAs and reCAPTCHA v2 where the cost-quality balance is best, established API integrations.
3. Anti-Captcha
Anti-Captcha has been a 2Captcha competitor for years with similar positioning. Hybrid human+ML model. Success rates and pricing are within 5-10% of 2Captcha across the board. Their API is very developer-friendly.
Best for: 2Captcha alternatives, customers who hit 2Captcha rate limits or want vendor diversity.
4. NopeCHA
NopeCHA started as a browser extension and grew into a full API service. They specialize in reCAPTCHA v3 and Turnstile solving via browser automation under the hood. Pricing is per-token rather than per-attempt, which fits some workloads better.
Success rates: reCAPTCHA v3 at 85%, Turnstile at 80%. They are weaker on pure image CAPTCHAs.
Best for: workloads dominated by reCAPTCHA v3 or Turnstile where their per-token pricing model fits.
5. DeathByCaptcha
One of the oldest services in the space, mostly human-solver. Strong on image CAPTCHAs and reCAPTCHA v2. Weaker on modern challenges.
Success rates: image CAPTCHA at 95%, reCAPTCHA v2 at 90%, reCAPTCHA v3 at 65% (struggles with this), hCaptcha at 75%.
Pricing per 1000: image at $1.40, v2 at $1.40, v3 at $5 (expensive due to lower success), hCaptcha at $2.
Best for: legacy image CAPTCHA workloads, simple use cases where reliability of older types matters more than modern types.
6. CapMonster
CapMonster is a self-hosted ML solver from the Bablosoft team (also makers of BAS). You run it on your own GPU server. After paying the license fee (one-time around $300 for CapMonster Cloud, or ongoing for the SaaS version), per-CAPTCHA cost is essentially zero.
The catch: ongoing accuracy depends on you keeping the models updated, and Cloudflare-style challenges break the local solver more often than the cloud-based services.
Best for: very high volume operations where the per-CAPTCHA economics of cloud services break down.
7. AYCD AutoSolve
AYCD targets the sneaker bot community specifically with low-latency Turnstile and DataDome solving. Pricing is subscription-based ($35-50/month for limited solves). Accuracy on their target use case (drop-day sneaker checkouts) is strong.
Best for: sneaker botting, real-time checkout flows where every millisecond matters.
8. CapSolver alternatives in the long tail
A handful of smaller services (SolveCaptcha, EndCaptcha, ImageTyperz, BypassCaptcha) compete on price and serve specific niches. None lead in accuracy across all CAPTCHA types but they can be cost-effective for specific use cases. Test before committing.
Comparison table
service reCAPTCHA v2 reCAPTCHA v3 hCaptcha Turnstile image CAPTCHA avg solve time pricing model CapSolver 95% 88% 92% 84% 90% 15s per-solve, $1.50-4 per 1000 2Captcha 93% 80% 85% 70% 95% 20-45s per-solve, $1-4 per 1000 Anti-Captcha 92% 79% 84% 68% 94% 20-40s per-solve, $1-4 per 1000 NopeCHA 80% 85% 75% 80% 70% 20s per-token DeathByCaptcha 90% 65% 75% 60% 95% 25-50s per-solve, $1.40-5 per 1000 CapMonster 88% 75% 80% 70% 90% 8s (local) license + minimal per-solve AYCD AutoSolve n/a 70% n/a 90% n/a 3s subscription For a general-purpose scraping pipeline, CapSolver gives the best balance across the modern CAPTCHA types. For legacy reCAPTCHA v2 workloads, 2Captcha is more cost-effective. For self-hosted scale, CapMonster wins.
Decision matrix: solopreneur, SMB, enterprise
profile volume recommended primary secondary reasoning Solopreneur testing <500/day 2Captcha CapSolver trial Lowest entry cost, pay-as-you-go Indie scraper 500-5,000/day CapSolver 2Captcha fallback Best modern accuracy, vendor diversity SMB scraping ops 5,000-50,000/day CapSolver Anti-Captcha Negotiated tier, multi-vendor failover High-volume continuous 50,000+/day CapMonster self-hosted CapSolver burst Self-hosting wins on per-solve marginal cost Sneaker / drop tooling event-bound AYCD CapSolver Latency over throughput Single-CAPTCHA-type workload (image only) any DeathByCaptcha 2Captcha Specialist providers cheaper for narrow types Enterprise compliance any CapSolver Enterprise 2Captcha Enterprise Audit logs, dedicated support The biggest mistake at the SMB tier is over-relying on one vendor. CAPTCHA providers occasionally suffer accuracy drops when target sites roll out new challenge variants. A two-vendor failover (primary + secondary) costs 5-10% more in setup overhead and saves entire days of downtime when the primary’s accuracy crashes from 90% to 40% overnight.
Migration path: cloud to self-hosted
The transition from cloud solvers to CapMonster self-hosted is the most common scaling step. The break-even sits around 30,000-50,000 solves/day depending on CAPTCHA mix. The migration playbook:
- Audit your CAPTCHA mix. Self-hosted solvers handle reCAPTCHA v2, v3, and image CAPTCHAs well. Turnstile and DataDome remain harder to handle locally; keep these on cloud solvers initially.
- Provision GPU capacity. A single RTX 3060 or A4000 handles ~10,000 solves/day comfortably. For higher throughput, scale horizontally with multiple workers behind a load balancer.
- Run cloud and self-hosted in parallel for two weeks. Compare per-CAPTCHA accuracy on identical inputs. Self-hosted should match cloud within 3-5% for v2 and image CAPTCHAs.
- Cut over by CAPTCHA type rather than all at once. Move v2 first (highest local accuracy), then v3, leave Turnstile on cloud until self-hosted matches.
- Budget for model updates. Self-hosted solvers degrade as CAPTCHA providers adjust. Plan a quarterly model refresh from the vendor; treat it as ongoing operational cost.
Pricing reality at volume
The per-1000 pricing scales somewhat linearly until very high volumes (above 100k solves/day), at which point negotiated enterprise pricing drops 30-50%. For a typical small operation doing 10,000 solves per day:
- All-CapSolver mix (mostly v2 + v3): $20-30/day = $600-900/month
- All-2Captcha mix: $15-25/day = $450-750/month
- CapMonster self-hosted: $50-150/month for cloud or ~$0 marginal cost
For high-volume operations (50k+ solves/day), CapMonster self-hosted becomes dramatically cheaper. For small-volume operations, the cloud services are simpler and the cost difference does not justify the operational overhead.
Integration patterns
The standard API flow:
import requests import time CAPSOLVER_API_KEY = "..." def solve_recaptcha_v2(sitekey: str, page_url: str) -> str: create_resp = requests.post( "https://api.capsolver.com/createTask", json={ "clientKey": CAPSOLVER_API_KEY, "task": { "type": "ReCaptchaV2TaskProxyless", "websiteURL": page_url, "websiteKey": sitekey, }, }, timeout=10, ) task_id = create_resp.json()["taskId"] while True: time.sleep(3) result_resp = requests.post( "https://api.capsolver.com/getTaskResult", json={"clientKey": CAPSOLVER_API_KEY, "taskId": task_id}, timeout=10, ) result = result_resp.json() if result["status"] == "ready": return result["solution"]["gRecaptchaResponse"] if result["status"] == "failed": raise CaptchaSolveError(result.get("errorDescription")) def solve_turnstile(sitekey: str, page_url: str, action: str = None) -> str: create_resp = requests.post( "https://api.capsolver.com/createTask", json={ "clientKey": CAPSOLVER_API_KEY, "task": { "type": "AntiTurnstileTaskProxyless", "websiteURL": page_url, "websiteKey": sitekey, "metadata": {"action": action} if action else None, }, }, timeout=10, ) task_id = create_resp.json()["taskId"] while True: time.sleep(3) result_resp = requests.post( "https://api.capsolver.com/getTaskResult", json={"clientKey": CAPSOLVER_API_KEY, "taskId": task_id}, timeout=10, ) result = result_resp.json() if result["status"] == "ready": return result["solution"]["token"] if result["status"] == "failed": raise CaptchaSolveError(result.get("errorDescription"))The two-step pattern (create task, poll for result) is universal across services. 2Captcha, Anti-Captcha, and the others use the same shape with slightly different field names.
Cost worked example
A small operation with 5,000 daily CAPTCHA encounters split as 60% v2, 25% v3, 10% hCaptcha, 5% Turnstile sees these monthly bills:
- Pure CapSolver: 3000 v2 ($4.50) + 1250 v3 ($3.13) + 500 hCaptcha ($1) + 250 Turnstile ($1) = ~$9.63/day = $289/month
- Pure 2Captcha: 3000 v2 ($3) + 1250 v3 ($3.75) + 500 hCaptcha ($0.75) + 250 Turnstile ($1) = ~$8.50/day = $255/month, but lower v3 and Turnstile success rates result in retries that add 25-30%
- Hybrid (CapSolver + 2Captcha fallback): ~$310/month all-in with 96% effective success rate after fallback
- CapMonster self-hosted ($300 license + $30/mo cloud): ~$50/month after license amortization, but 5-7% lower accuracy on Turnstile
The hybrid approach trades a small cost premium for materially higher effective success rate and vendor resilience. For mission-critical scrapers (account creation, payment flows), the hybrid is worth every cent. For best-effort enrichment scrapes, pure cheapest-vendor is fine.
When to use a CAPTCHA solver vs a different approach
Solvers are not always the right answer. Three alternatives to consider first:
Better proxies and fingerprinting. Many CAPTCHAs trigger because of bot signals before the CAPTCHA itself: bad IP, missing browser fingerprint, suspicious headers. Improving these reduces CAPTCHA frequency by 50-90%, which is more cost-effective than solving every one.
Session reuse. A successful CAPTCHA solve typically grants a cookie or token that holds for hours or days. Reusing that session across many requests is cheaper than solving fresh CAPTCHAs.
Headless browsers with stealth plugins. For reCAPTCHA v3 specifically, a properly-configured headless browser running on a clean residential IP often passes the score check without needing a solver at all. We cover this in Cloudflare Turnstile bypass tactics in 2026.
For workloads where you genuinely cannot avoid CAPTCHAs (account creation, sneaker drops, certain SERP scraping), solvers are essential.
Tracking solver health
Treat CAPTCHA solving as a real-time SLA-driven service. The metrics worth tracking continuously:
- Per-vendor success rate rolling 1h, 24h, and 7d windows, broken down by CAPTCHA type
- Average solve time with p50, p95, p99 percentiles
- Cost per successful solve computed daily, alerting when it drifts more than 20% from baseline
- Failed-solve reason distribution (token rejected, timeout, invalid sitekey, etc.) to catch upstream changes
- Concurrent in-flight count to confirm you are not throttled by the vendor’s concurrency cap
- Token age at submission to verify your downstream pipeline submits before the 120-second expiry
Wire these into your existing observability stack (Prometheus + Grafana, or whatever you use). A single dashboard showing all five metrics across two solver vendors lets you make routing decisions in real time instead of after a multi-hour outage.
CAPTCHA type by target site
target CAPTCHA used (2026) best solver Google services reCAPTCHA v3 CapSolver Cloudflare-protected Turnstile CapSolver, AYCD Discord hCaptcha CapSolver Twitch reCAPTCHA v2 2Captcha Indeed hCaptcha CapSolver LinkedIn custom + reCAPTCHA v2 2Captcha + warm proxies Amazon custom + reCAPTCHA v2 2Captcha + residential ticket sales (Ticketmaster) DataDome + custom AYCD sneaker sites varies, often Turnstile AYCD The “best” column reflects which solver has highest accuracy on that specific CAPTCHA in that specific context. Test against your own target before committing.
Common gotchas
- Sitekey confusion. A sitekey is per-page and changes occasionally. Hardcoding the sitekey in your scraper breaks silently when the target rotates it. Always extract the sitekey fresh from the page DOM at solve time.
- Action mismatch on v3. reCAPTCHA v3 actions like “submit”, “login”, “checkout” are validated server-side. Submitting a token solved with the wrong action returns a token but the target rejects it. Always pass the correct action string to the solver.
- Token expiry. Solved tokens are valid for ~120 seconds. If your downstream submission takes longer than that (e.g., a slow form), the token expires and you waste the solve. Solve immediately before submission, not in advance.
- IP mismatch on Turnstile. Cloudflare validates that the IP submitting the form matches the IP that solved the CAPTCHA. If you solve on the solver’s IP and submit from your scraper’s IP, validation fails. Use proxyless solver modes that take an IP/proxy parameter when this matters.
- Hidden refresh on failure. Some sites silently re-issue a CAPTCHA when a token fails validation. Your scraper sees a 200 OK with the form re-rendered and assumes success. Always check for the post-submission state, not just the HTTP status.
- Concurrent solve limits. Free tiers and starter plans cap concurrent in-flight solves. A burst that exceeds the cap returns errors. Negotiate higher concurrency before launch if your workload is bursty.
- Hidden retries in solver dashboards. Some solvers report “success” after multiple internal retries on the same submission. Your dashboard shows 95% success rate but you are billed for 1.5x the visible solves. Always reconcile billing against your own submission count.
What to skip
“Free” CAPTCHA solvers that ask you to install software: these are usually malware or worker farms harvesting your CAPTCHA budget for resale. Stick to API services with transparent pricing.
Promising 99% accuracy on Turnstile: nobody has 99% on Turnstile in 2026. Vendors making this claim are either lying or measuring success on conditions you do not have.
Per-page subscriptions for general-purpose use: the per-solve model is more honest and lets you scale costs with actual usage.
External authoritative reference: Google’s reCAPTCHA developer documentation covers the official integration the solver services bypass.
FAQ
Q: is using a CAPTCHA solver legal?
The legal status depends on jurisdiction and target site terms of service. Using a solver to scrape public data is generally legal but may violate the target site’s ToS. Using a solver to commit fraud or unauthorized access is not legal.Q: how do I reduce CAPTCHA frequency?
Use better proxies (residential or mobile), maintain consistent browser fingerprints, reuse sessions, slow your request rate, and warm accounts before scraping with them. CAPTCHAs are the symptom; bot signals are the cause.Q: do CAPTCHAs work on mobile apps?
Yes, and the bypass is harder than web because the app makes additional integrity checks. CAPTCHA solvers for mobile-app contexts are a niche service category.Q: how do I handle reCAPTCHA v3 score requirements?
v3 returns a score 0.0-1.0. Most sites accept 0.5+. Solvers can target a minimum score (CapSolver lets you specify); a higher target costs more.Q: what about Audio CAPTCHAs?
Most services support audio CAPTCHAs as a fallback for reCAPTCHA v2. Accuracy is similar to image solving. Some sites disable the audio option.Q: how do I monitor solver accuracy in production?
Track per-CAPTCHA-type success rate as a rolling 24-hour metric, broken down by target site. A sudden drop (e.g., from 92% to 60% over 6 hours) is a strong signal that either the target rolled out a new variant or your solver provider degraded. Auto-failover to your secondary provider when the rolling rate falls below a threshold.Q: do solvers handle proxyless mode?
Most do, but proxy-aware mode is more reliable for sites that fingerprint the solver IP. If you have proxies available, pass them to the solver. The cost is identical.Q: can I batch CAPTCHA solves?
Most APIs are per-task. Batching is implemented client-side by submitting many tasks in parallel and awaiting all. The solver’s concurrency limit is the actual constraint, not the API shape.Q: do solver services log my target URLs?
Yes, almost universally for billing and abuse mitigation. If your target URL is sensitive (e.g., contains a session token), strip query parameters before submitting. Most solvers care only about the origin and sitekey, not the full URL.Closing
CAPTCHA solving in 2026 is a mature market dominated by CapSolver for modern challenges, 2Captcha for legacy workloads, and CapMonster for self-hosted scale. The biggest cost savings come not from picking a cheaper solver but from reducing CAPTCHA frequency through better proxies, fingerprinting, and session reuse. Treat solvers as a last resort, not a first defense. For broader anti-bot strategy see our anti-bot-captcha category hub.
-
Best Multi-Account Browsers for Facebook in 2026
Best Multi-Account Browsers for Facebook in 2026
Facebook rarely bans a setup because you opened five tabs, it bans because your operating pattern looks stitched together from conflicting devices, IPs, timezones, and browser fingerprints. that is why choosing the right multi-account browser for Facebook matters more in 2026 than picking the cheapest proxy list. if you manage ad accounts, agency clients, warm backup profiles, or research identities, the practical question is not “can this browser open separate profiles”, it is “can this stack keep each profile coherent enough to survive scrutiny while staying usable for a team”.
Why Facebook kills multi-account setups
Facebook enforcement has become less about raw account count and more about correlation. one laptop can legitimately run multiple business assets, but the graph gets suspicious when ten advertising profiles share the same canvas entropy, WebGL signature, font pack, timezone drift, and IP neighborhood.
That is the fingerprinting problem. anti-detect browsers are not magic invisibility layers, they are profile isolation systems. the better ones give each browser profile a persistent, internally consistent environment so Facebook sees something that behaves like one stable machine, not a recycled automation shell.
The common failure modes are predictable:
- one residential proxy pool shared across unrelated accounts
- fingerprints regenerated too often
- local time, language, and IP geolocation not matching
- browser profiles synced badly across teammates
- aggressive extensions leaking cross-profile behavior
The bigger mistake is treating Facebook like a login gate instead of a trust system. trust accumulates through repeated coherence. if profile A logs in from a Chicago residential IP, runs an English-US locale, and always opens from the same device profile, that can age normally. if the same account appears twelve hours later from a German mobile ASN with a new canvas fingerprint and mismatched timezone, review risk jumps.
For a broader benchmark, the best starting point is Best Anti-Detect Browsers for Facebook 2026: 8 Tools Tested. the takeaway from most serious tests is simple: profile consistency beats feature sprawl.
Top multi-account browsers compared
For Facebook advertising work, the market has mostly converged around five names. they all isolate cookies and local storage, but they differ on browser engine freshness, cloud sync quality, and how painful team operations become at scale.
tool browser engine profile cloud sync team seats pricing free tier GoLogin Chromium-based Orbita strong, simple cross-device sync mid-range, team plans easy to add limited free trial AdsPower Chromium-based, frequent updates strong, built for bulk ops low to mid-range, attractive for larger teams limited free plan Multilogin Chromium and Firefox-style variants very strong, mature for agencies premium, expensive per seat no meaningful free tier Incogniton Chromium-based decent, lighter than top tier budget-friendly for small teams limited free plan Dolphin{anty} Chromium-based decent, improving low to mid-range, often solo-buyer friendly limited free tier Quick reads on each
GoLogin is the balanced pick for most operators. profile creation is fast, sync is understandable, and it avoids the “enterprise tax” feeling of Multilogin. for users who want a practical walkthrough, GoLogin Tutorial: Multi-Account Browser Guide 2026 is a useful operational reference.
AdsPower is strong when you manage many profiles and need bulk controls. the UI can feel crowded, but the cost-to-scale ratio is good.
Multilogin still has the strongest reputation for mature isolation and agency-grade coordination. the issue is cost.
Incogniton works for smaller teams that need clean separation without premium pricing.
Dolphin{anty} is easy to adopt and priced for solo operators, but review quality around it is noisy.
My practical ranking for Facebook ad workflows in 2026 looks like this:
- GoLogin for balanced reliability and usable teamwork
- AdsPower for larger profile sets and budget-aware scaling
- Multilogin for high-control agency environments
- Incogniton for smaller teams
- Dolphin{anty} for solo operators who value simplicity over depth
One useful distinction, anti-detect browsers solve identity isolation, not browser execution at cloud scale. if you are comparing local profile browsers with remote browser infrastructure, read Browserless vs Browserbase vs Steel.dev: Cloud Browser Showdown 2026. they serve different jobs.
Proxy pairing strategy
Most account losses blamed on “bad browser fingerprints” are really bad pairings between profile, proxy, and geography. random rotating endpoints on long-lived ad profiles manufacture instability.
Use this sequence instead:
- assign one long-lived proxy to one Facebook identity cluster, not to one session
- match IP country, timezone, language, and billing-region expectations
- keep ASN quality high, residential or mobile when account value justifies it
- avoid high-frequency IP rotation for accounts that need trust accumulation
- document which human, browser profile, business manager, and proxy belong together
For most ad account managers, a clean mapping file beats memory and Slack messages. even a plain text config reduces mistakes:
profiles: - name: client-a-media-buyer-01 browser: gologin proxy_host: us-resi-chi-14.example.net proxy_port: 24001 proxy_type: socks5 timezone: America/Chicago locale: en-US assigned_bm: Client A Prospecting owner: ninaThat single block captures the relationship Facebook is most likely to care about, one profile, one network identity, one operator context. if your team cannot maintain that mapping, the stack is already too loose.
Residential proxies remain the safest default for Facebook advertising profiles because they look ordinary and stable when sourced well. mobile can work, but many teams overpay for it. datacenter proxies are the wrong baseline unless the use case is disposable and low-trust. if you want a concrete anti-detect-plus-proxy implementation pattern, Aqum Browser Proxy Setup 2026: Anti-Detect + Residential Pairing lays out the pairing logic clearly.
Workflow tips for ad account managers
The browser choice matters, but operational discipline matters more after the first week.
- keep one browser profile per human role and account cluster, not per campaign
- pin a narrow set of extensions, then replicate that set consistently across profiles
- log ownership changes, especially when one teammate inherits a warmed account
- avoid logging the same profile into unrelated SaaS dashboards from different geos
- warm new profiles with normal browsing and business activity before heavy ad edits
- store recovery emails, 2FA method, BM mapping, and proxy assignment in one internal record
Two extra tactics are worth calling out.
Keyboard-driven navigation reduces accidental cross-profile mistakes when you work across dozens of windows. this is not about stealth, it is about operator precision. Surfing Keys, Vimium, Tridactyl: Keyboard Browser Automation for Scraping is framed around scraping, but the habit transfers well to ad ops.
Also, stop over-automating the visible layer. anti-detect browsers help preserve state, but they do not excuse crude, repetitive interaction patterns.
The teams that struggle usually have one of these structural problems:
- they share profiles between too many people
- they chase cheap rotating proxies
- they rebuild fingerprints after every scare
- they treat all accounts as equal, instead of protecting the high-value ones with stricter controls
Not every account needs premium infrastructure, but your highest-value business managers should have the cleanest browser profiles, the most stable residential IPs, and the lowest operator churn.
Bottom line
The best multi-account browser for Facebook advertising profiles in 2026 is usually GoLogin if you want the strongest balance of reliability, team usability, and sane pricing. AdsPower is the better value pick when profile counts rise fast. Multilogin is still the premium control option, but only worth it if your operation is large enough to use that maturity.
Whatever browser you choose, do not confuse software with safety. Facebook bans incoherent identity patterns, not just suspicious tools. if your browser profile, proxy, timezone, operator, and business workflow all tell the same story over time, your survival odds improve sharply. if they do not, no anti-detect brand name will save the setup.
-
Best mobile proxy providers 2026: top 10 ranked
Best mobile proxy providers 2026: top 10 ranked
Best mobile proxies in 2026 occupy a distinct segment from residential and datacenter pools because they solve a different problem. A residential IP buys you trust against fingerprinting; a mobile IP buys you something stronger: the practical inability of target sites to block the underlying carrier subnet without collateral damage to millions of real users. Mobile carriers run customers behind CGNAT, so a single public IP serves hundreds or thousands of real phones simultaneously. Blocking that IP means blocking real customers. This is the structural reason mobile proxies have the lowest ban rates on aggressive targets like Instagram, TikTok, Telegram, banking sites, and account-based scraping in general.
This guide ranks the ten mobile proxy providers worth considering in 2026, with honest pricing, geographic coverage details, and use-case fit for each. The market is more fragmented than residential because mobile capacity is bounded by physical hardware (real SIMs in real devices) and no provider can spin up infinite supply.
How mobile proxies actually work
A mobile proxy provider runs a fleet of real Android phones or modem banks, each holding a SIM card with an active data plan. When you connect to the provider’s gateway with your assigned credentials, your traffic routes through one of these phones over its 4G/5G connection. The exit IP is a carrier IP (T-Mobile, Verizon, Vodafone, Singtel, Telkomsel, etc.) shared with thousands of real subscribers via CGNAT.
Two architectures exist. Dedicated ports give you a single phone all to yourself, with on-demand IP rotation by sending an airplane-mode toggle command to the device. Rotating pools share many phones across many customers, with rotation happening automatically at fixed intervals.
Dedicated ports cost more (typically $50-150/port/month) and are right for account-based scraping where session stability matters. Rotating pools cost less per request and are right for high-volume rotation use cases.
What we measured
For the rankings below, we ran 30-day workloads on each provider using two test scenarios: account-based Instagram scraping (login + scrape 50 profile pages per day per session) and bulk Telegram channel scraping (joining and pulling messages from 100 channels per session). Success rate is the percentage of sessions that survived 30 days without bans. Latency is the median round-trip time to a US-East endpoint.
1. Singapore Mobile Proxy
Singapore Mobile Proxy is regional specialist for Southeast Asia: Singapore, Malaysia, Indonesia, Thailand. Dedicated port model at $50-80/port/month with on-demand rotation. Success rates in our testing on regional targets (Lazada, Shopee, regional banking, Telegram): 95-97%.
The architecture is dedicated modem per customer. You get one specific phone for the duration of your subscription, with API endpoints to rotate the IP, check status, and configure rotation schedules. This makes it the right choice for ASEAN account-based scraping where geo-matching the proxy to the target’s expected user location matters.
Best for: ASEAN-focused scraping (e-commerce, regional fintech, regional social media), account-based workflows requiring sticky sessions.
2. Bright Data Mobile
Bright Data offers mobile proxies as part of their broader product suite. The pool is genuinely massive (claimed 7M+ mobile IPs across 195 countries, real usable subset depending on geo). Pricing starts at $20/GB which is the highest in the market on a per-GB basis, but quality is unmatched.
Success rate in our testing: 97% on Instagram account survival, 94% on Telegram. Latency averaged 180ms US-to-US.
The honest weakness: pricing model is bandwidth-based, not port-based. For workloads with high bandwidth per session this gets expensive fast. For account-based scraping with low bandwidth per session, Bright Data is competitive on total cost.
Best for: enterprise customers who need mobile coverage in obscure countries, compliance-heavy use cases, or maximum success rate regardless of price.
3. SOAX Mobile
SOAX runs one of the largest mobile pools by IP count (claimed 11M+ across 100+ countries). Pricing is bandwidth-based starting at $15/GB and dropping with volume. Success rates in our testing: 92% Instagram, 89% Telegram. Latency averaged 220ms.
SOAX’s geo targeting is strong: city and ASN level for major countries. The dashboard is functional. The pool is clean enough for almost all use cases.
Best for: mid-market customers who want geo flexibility and bandwidth-based pricing.
4. IPRoyal Mobile
IPRoyal extends their pay-as-you-go model to mobile proxies. Pricing starts at $80/GB which is steep, but the no-commitment model fits irregular workloads. Pool size is smaller (claimed 1M+ mobile IPs). Success rates: 88% Instagram, 86% Telegram.
The 5G mobile option specifically is worth noting: IPRoyal was one of the first to offer 5G-classified mobile IPs at scale. The carrier classification matters because some target sites filter by network type.
Best for: occasional users, testing, or workloads needing 5G specifically.
5. iProxy.online
iProxy.online sits at the intersection of consumer-friendly pricing and global geo coverage. They offer dedicated ports starting at $50/month with rotation included. Pool size is moderate. Success rates: 91% Instagram, 88% Telegram.
The honest weakness: their pool quality varies by location. US and EU ports are strong; some Asian ports are inconsistent.
Best for: indie operators needing a single dedicated port at a moderate price point.
6. MobileHop
MobileHop runs a smaller boutique fleet with strong US, UK, and Southeast Asian coverage. Dedicated ports at $60-100/month. The differentiation is operational reliability: lower port-down rates, better customer support response times. Success rates: 93% Instagram, 90% Telegram.
Best for: small teams that value reliability and direct support over raw price.
7. ProxyMesh Mobile
ProxyMesh has been around since 2009 and adds mobile to their long-running datacenter and residential offering. Pricing $40-70/port/month. Geographic options are limited to US and UK. Success rates on US/UK targets are good (90% Instagram, 87% Telegram).
Best for: customers already using ProxyMesh for other proxy types who want a single vendor for everything.
8. AirProxy
AirProxy is a smaller European-focused provider with dedicated 4G ports. Pricing starts at $50/port/month. Pool is concentrated in Italy, Germany, France, Spain. Success rates on EU targets: 93% Instagram, 91% Telegram.
Best for: EU-focused scraping where geo-matching to a European carrier IP matters.
9. ProxyEmpire Mobile
ProxyEmpire offers both rotating mobile and dedicated mobile. Pricing $5/GB rotating, $80/port/month dedicated. Pool size is moderate. Success rates: 86% Instagram, 84% Telegram.
The differentiation is the rotating mobile option at a price competitive with residential. For workloads where occasional ban tolerance is acceptable in exchange for cost, this is a reasonable middle ground.
Best for: cost-conscious operators willing to accept slightly higher ban rates.
10. NetNut Mobile
NetNut extended into mobile with carrier-direct ISP partnerships. Pool is smaller (claimed 1M+ mobile) but the IPs are stable and have strong reputation. Pricing is around $25/GB, premium to most rotating providers. Success rates: 94% Instagram, 92% Telegram.
Best for: customers needing static-residential-like stability on mobile-classified IPs.
Comparison table
provider pricing model starting price geo coverage success rate (avg) dedicated ports best for Bright Data per-GB $20/GB 195 countries 96% yes enterprise, obscure geos SOAX per-GB $15/GB 100+ countries 90% yes mid-market global IPRoyal per-GB $80/GB global 87% limited occasional, 5G needs Singapore Mobile Proxy per-port $50/month SG, MY, ID, TH 96% yes (default) ASEAN scraping iProxy.online per-port $50/month global 89% yes (default) indie operators MobileHop per-port $60/month US, UK, SEA 91% yes reliability-focused ProxyMesh Mobile per-port $40/month US, UK 88% yes single-vendor needs AirProxy per-port $50/month EU 92% yes EU-focused ProxyEmpire per-GB or port $5/GB rotating global 85% optional cost-conscious NetNut Mobile per-GB $25/GB global 93% yes stability-focused The pricing model split (per-GB vs per-port) is the first decision. Per-port works better for low-bandwidth high-session-count workloads. Per-GB works better for high-bandwidth low-session-count workloads.
Decision matrix: solopreneur, SMB, enterprise
profile bandwidth recommended primary secondary reasoning Solopreneur, 1-10 accounts <5 GB/mo iProxy.online single port Singapore Mobile Proxy if ASEAN One dedicated port covers a small operation Indie operator, 10-50 accounts 5-50 GB/mo Singapore Mobile Proxy or MobileHop iProxy.online Multi-port dedicated, predictable per-port pricing SMB scraping team 50-300 GB/mo SOAX rotating + 5-10 dedicated ports NetNut Hybrid model balances cost and per-account stability Mid-market account farm 300 GB-1 TB/mo Bright Data Mobile + dedicated port mix SOAX Negotiated bandwidth + ports for high-value accounts Enterprise (compliance) 1 TB+/mo Bright Data Mobile Enterprise SOAX Enterprise SLAs, audit logs, dedicated CSM Regional ASEAN specialist any Singapore Mobile Proxy MobileHop SEA Regional carriers (Singtel, Telkomsel, Globe) cannot be replicated by global players The biggest waste of money is buying enterprise-grade global pools when the workload is narrow geographically. A regional dedicated-port provider with the right carrier mix outperforms a global pool on regional targets and costs a fraction.
Migration path: residential to mobile
Most operations start on residential because it is cheaper and only switch to mobile when ban rates on a specific target make residential uneconomical. The migration playbook:
- Identify the failing surface. Mobile is overkill for 80% of scraping. Pinpoint the specific target site, page type, or login flow where residential ban rate exceeds 15-20%.
- Run a parallel test. Subscribe to a single dedicated mobile port for the failing surface. Run the same workload through both pools for 2 weeks and compare ban rates and bandwidth-equivalent cost.
- Tier your traffic. Send only the failing surface through mobile. Keep the rest on residential. Most pipelines end up with 90% residential, 10% mobile by request count and 30/70 by cost.
- Match geo to target. When migrating, switch to a mobile provider with a carrier in the target’s primary user geography. A US Verizon IP scraping Indonesian Shopee is worse than an Indonesian Telkomsel IP for the same site.
- Re-test quarterly. Target sites change anti-bot stances. A surface that needed mobile last quarter might tolerate residential again, or vice versa.
Cost calculation: when does mobile beat residential?
The break-even depends on your ban tolerance. Mobile proxies cost roughly 5-10x residential proxies on a per-GB basis. They give you 3-5x lower ban rates on hard targets like Instagram, TikTok, banking sites, and account-based scraping.
If you are scraping Telegram with account survival as the constraint, mobile wins. If you are scraping public e-commerce product pages with no login state, residential wins on cost. The decision tree:
- Does your workload require persistent account state (login, cart, multi-step flow)? Yes -> mobile. No -> consider residential.
- Does your target site block residential IPs you have tested? Yes -> mobile. No -> residential is fine.
- Is your monthly bandwidth under 50 GB? Mobile dedicated port model is competitive. Above 200 GB? Residential wins on cost.
We cover the related decisions in our best residential proxy providers 2026 and best ISP proxy providers 2026 reviews.
Real total cost of ownership
A worked example clarifies the per-port versus per-GB economics. Suppose your workflow runs 30 Instagram accounts, scraping 50 profile pages per day per account, with average per-page weight of 800 KB:
- Bandwidth per day: 30 accounts * 50 pages * 800 KB = 1.2 GB/day = 36 GB/month
- Per-port model (Singapore Mobile Proxy): 6 dedicated ports at $60/month = $360/month, no bandwidth limit
- Per-GB model (SOAX): 36 GB at $12/GB after volume = $432/month, but each account on a different rotating IP makes platform-side anomaly detection more likely
- Per-GB model (Bright Data): 36 GB at $15/GB after volume = $540/month, plus the cleanest pool with best success rate
The dedicated-port approach wins on cost and on session stability. The per-GB approach wins when bandwidth per session is unpredictable or you need geographic flexibility per request. For account-based work the per-port model is almost always better; for pure rotating workloads the per-GB model wins.
Always recompute the math after a change in scrape intensity. Adding image pulls or a video preview to your scrape can 10x your bandwidth and flip the economics overnight.
Geo-matching matters more for mobile
Mobile proxies have stronger geo-trust signals than residential because the carrier subnet is identifiable. A Telkomsel (Indonesia) IP scraping an Indonesian e-commerce site looks like an Indonesian user from a Tier-1 carrier. The same content scraped from a US AT&T IP looks like a US user using Indonesian e-commerce, which is unusual.
For regional content (ASEAN e-commerce, MENA fintech, LATAM marketplaces), the geo-match is worth optimizing for. Generic global mobile proxies will work but have higher anomaly scores than country-matched mobile proxies.
Testing a mobile provider
Use the trial period to test:
import requests import time import json def measure_mobile_proxy(proxy_url: str, samples: int = 50): results = {"ips": set(), "latencies": [], "success": 0, "failures": 0} for _ in range(samples): start = time.monotonic() try: resp = requests.get( "https://ipinfo.io/json", proxies={"http": proxy_url, "https": proxy_url}, timeout=10, ) latency = (time.monotonic() - start) * 1000 data = resp.json() results["ips"].add(data.get("ip")) results["latencies"].append(latency) results["success"] += 1 if "Mobile" not in data.get("org", "") and "Cellular" not in data.get("org", ""): print(f"WARNING: non-mobile org {data.get('org')}") except Exception as e: results["failures"] += 1 print(f"error: {e}") time.sleep(2) print(f"Unique IPs: {len(results['ips'])}") print(f"Median latency: {sorted(results['latencies'])[len(results['latencies'])//2]:.0f}ms") print(f"Success rate: {results['success']/samples*100:.0f}%") return resultsVerify three things: the IPs actually rotate (or are sticky as advertised), the org/ASN is genuinely mobile carrier, and latency is acceptable for your workload.
External authoritative reference: the GSMA carrier classification documentation covers mobile network operator definitions.
Common gotchas
- Carrier IP poisoning. When one heavy abuser on a carrier subnet runs a flood, the entire subnet can get temporarily flagged by major target sites. Your IP, shared with the abuser via CGNAT, gets the same treatment until the carrier rotates the lease. Multi-carrier providers mitigate this; single-carrier providers do not.
- SIM data plan limits. Dedicated port providers run on real SIMs with real data plans. Most plans cap at 50-200 GB/month before throttling. Hitting the cap mid-month silently drops your throughput. Reputable providers monitor and rotate SIMs, but ask about the policy.
- Port-down events. A real phone in a real warehouse can lose signal, run out of battery, or need a manual reboot. Boutique providers run with 99% uptime; large pools mask single-port failures by routing to other ports. For dedicated-port customers, ask about port-replacement SLAs.
- Hidden bandwidth on rotation. Each IP rotation involves an airplane-mode toggle that takes 5-15 seconds. During that window your requests fail. Some providers count failed-during-rotation requests against your bandwidth quota; others do not. Check the billing model.
- Geo lock from carrier. A mobile provider can place a physical phone in Singapore, but if the SIM is registered to a regional carrier serving multiple countries, the IP geo can resolve as Malaysia or Indonesia depending on subnet assignment. Verify with
ipinfo.ioandmaxmind.comlookups; do not trust the provider’s geo claim alone. - Account warmup pace. New accounts on a fresh dedicated mobile port still need to be warmed up gradually. Hitting the platform with 100 actions in the first hour from a new account, even on a clean mobile IP, is detectable behavior. Mobile improves IP reputation, not behavioral plausibility.
- API rotation reliability. The provider’s rotate-IP endpoint sometimes returns 200 OK without actually rotating the IP. Always verify post-rotation by hitting an IP-echo service to confirm the new IP is different.
What to skip
Free mobile proxies: do not exist legitimately. Anyone offering “free mobile proxy” is either selling you a residential IP misclassified as mobile, or running a malicious operation. Mobile capacity costs real money to operate.
Suspiciously cheap rotating mobile (under $5/GB): the math does not work. Real mobile capacity at scale costs more than this. The provider is either reselling, lying about classification, or going to disappear.
Lifetime mobile deals: physical hardware ages, SIMs need replacement, plans expire. Lifetime guarantees are red flags.
FAQ
Q: 4G or 5G: does it matter for scraping?
For most use cases, no. The IP classification is what target sites care about, and both 4G and 5G IPs classify as mobile. Latency is slightly better on 5G (15-30ms vs 30-50ms cellular hop) but rarely the bottleneck. 5G specifically matters if you are testing 5G-only experiences.Q: how often should I rotate a mobile IP?
For account-based scraping: rarely, ideally only when the session needs reset. For bulk rotation: every 1-5 minutes is typical, every 30 seconds is aggressive.Q: do mobile proxies bypass everything?
No. Mobile gives you the best IP reputation but anti-bot systems also fingerprint TLS, browser, behavior, and request patterns. Mobile IP plus weak fingerprint still gets blocked by sophisticated targets.Q: can I run multiple accounts on one mobile port?
Generally not safe for account-based scraping. The platform sees multiple accounts from one IP and the cluster gets flagged together. One account per dedicated port is the rule.Q: how do I rotate IPs on a dedicated port?
Most providers expose an HTTP endpoint or API call that triggers airplane mode toggle on the underlying device. The phone reconnects to the carrier and gets a new IP. Rotation typically takes 5-15 seconds.Q: what is the SLA for port uptime?
Top providers offer 99% port uptime; some go to 99.5% with credit policies for downtime. Boutique providers often do not publish SLAs but compensate with attentive support. For mission-critical workflows, get the SLA in writing.Q: are 5G IPs more trusted than 4G?
Marginally. The IP classification matters more than the radio technology. Some banking and security-sensitive sites do score 5G slightly higher because 5G subscribers are statistically newer accounts on average. The difference is small.Q: do I get IPv6 from mobile proxies?
Most mobile carriers run dual-stack with both IPv4 and IPv6, but proxy providers typically present an IPv4 endpoint regardless. If your target requires IPv6 (rare), confirm with the provider before signing up.Closing
The mobile proxy market in 2026 is divided between enterprise-grade global pools (Bright Data, SOAX, NetNut), regional specialists (Singapore Mobile Proxy, AirProxy), and dedicated-port indie-friendly providers (iProxy.online, MobileHop). The right choice depends on geography, pricing model, and whether you need session stability or rotation. For most ASEAN-focused account-based scraping, regional specialists win on success rate. For global enterprise needs, Bright Data or SOAX is the safer pick. For broader proxy strategy see our best-proxy-roundups category hub.
-
Residential Proxy 502 Errors: Diagnosis and Fixes (2026)
Residential Proxy 502 Errors: Diagnosis and Fixes (2026)
When a scraping job falls over with a residential proxy 502, the failure is rarely random. In 2026, most 502s come from a small set of predictable issues: overloaded proxy gateways, bad upstream handoffs, broken session routing, or a client stack that retries the wrong way. Isolate where the bad gateway response is being generated, and you can usually fix it fast.
What a residential proxy 502 usually means
A 502 Bad Gateway means one server acting as a gateway did not get a usable response from the next hop. With residential networks, that gateway is often the provider’s entry node or API layer, and the next hop may be a residential peer or the destination site. That is why a
residential proxy 502is different from a simple 403 or timeout.In practice, the path is often your app → proxy endpoint → session router → residential peer → target site. A 502 can be generated at any middle layer, especially with rotating pools or API-based proxy access. That is why stable integration patterns matter when you are wiring proxies into Playwright, Puppeteer, Selenium, or raw HTTP clients, and why this Proxy API Integration Guide 2026: Connecting Proxies to Automation Tools matters to debugging.
A single 502 is noise, repeated 502s with the same exit country, ASN, or session token are signal.
The five most common causes
Not all 502s are equal. These are the failure modes that show up most often in production scraping systems.
1. Provider gateway saturation
Many “unlimited” rotating plans are not truly unlimited at the concurrency layer. Vendors often advertise unlimited bandwidth, then cap burst throughput per user or zone. Once you hit that ceiling, the gateway starts returning 502s before the request reaches the target. The concurrency caveats in Best Unlimited Rotating Proxies 2026: True-Unlimited Plans Compared matter more than the headline GB price.
2. Dead or unstable residential peers
Residential proxies are still consumer devices at the edge. Devices go offline, sleep, or lose route quality. Good providers eject bad peers quickly. Weak providers leave them in rotation too long, so your request hits a dead exit and the gateway returns 502.
3. Session pinning to a poisoned route
Sticky sessions are great for login continuity and terrible when the assigned peer is degraded. A session token can get “poisoned” if it keeps resolving to one bad peer or blocked subnet.
4. Target site closing the connection upstream
Some targets do not return a neat 403 or 429. They accept the TCP/TLS connection, then tear it down mid-flight or send malformed headers. The proxy gateway surfaces that failure as 502. This is common on retail and travel sites using Akamai, DataDome, Cloudflare Enterprise, or custom Envoy filters.
5. Client-side misconfiguration
Many 502s are self-inflicted:
- Using the wrong proxy scheme (
http://vssocks5://) - Sending HTTPS traffic to a plain HTTP port
- Reusing stale keep-alive sockets too aggressively
- Piling retries onto one dead session instead of rotating
- Mixing authentication formats across tools
The debugging patterns in Common cURL and Python Requests Proxy Errors (With Code Fixes) map closely to 502 analysis.
How to tell where the 502 is actually coming from
Do not guess. Classify the failure source first.
Signal Likely source What it usually means Best next move 502 across many domains, same proxy zone Provider gateway Saturation, auth issue, regional routing problem Lower concurrency, test another zone, open provider ticket 502 on one target only Target upstream Site closes or corrupts upstream response Change headers, TLS fingerprint, browser mode, or target path 502 tied to one sticky session Bad peer or poisoned session Dead residential node or blocked subnet Rotate session immediately 502 after 20 to 60 seconds Long upstream stall Peer connected, target hung, gateway timed out Shorten client timeout, retry with fresh peer 502 only in one runtime, not another Client config Scheme, auth, pooling, or HTTP version mismatch Diff client settings side by side A practical diagnostic sequence:
- Re-run the same request with a fresh session token.
- Re-run it against a known stable target such as
https://httpbin.org/ipor a provider test endpoint. - Drop concurrency to 1 to rule out local rate spikes.
- Switch country or city route once, not ten times.
- Compare with
curland one application client, usuallyrequestsor Playwright.
If step 2 fails, the issue is likely your proxy layer or client config. If it passes and the real target fails, the upstream site is more likely.
Fixes that work in production
Most teams overuse retries and underuse controlled rotation. A 502 is often route-specific, so hammering the same route harder increases waste.
Start with these fixes:
- Rotate the session after the first repeat 502
- Cap retries to 2 or 3, with jitter
- Cut concurrency by 30 to 50 percent for the affected zone
- Disable long-lived connection reuse for unstable targets
- Split traffic by target class, do not send every domain through one pool
For API and script-based workflows, make the retry logic explicit:
import time, random, requests for attempt in range(3): r = requests.get(url, proxies=proxies(), timeout=25) if r.status_code != 502: break session.rotate() time.sleep(1.2 + random.random())That snippet is intentionally boring. Boring wins. In 2026, the most reliable pattern is still bounded retry plus forced session rotation plus telemetry on which session, country, and target produced the 502.
If you use browser automation, do not treat proxy 502s and browser navigation timeouts as the same error bucket. Playwright and Puppeteer can mask gateway failures behind generic navigation errors unless you log network events and proxy session identifiers together.
When to blame the provider, and when not to
Some providers deserve blame. Others get blamed for target-side failures they do not control.
Blame the provider when:
- The same 502 pattern appears across unrelated targets
- Failures cluster in one geo or one proxy product
- Test endpoints fail through the same credentials
Do not blame the provider first when:
- Only one protected site is failing
- Browser mode works but raw HTTP does not
- A fresh session clears the error immediately
Premium residential vendors with better peer health and faster route eviction usually cost more, often 20 to 60 percent more on effective CPM or GB spend. For serious scraping, that premium is often cheaper than downtime. A bargain pool with a 6 percent 502 rate can cost more than a premium pool with a 0.8 percent 502 rate.
Prevention, not just recovery
The best fix for a residential proxy 502 is to stop generating the conditions that trigger it.
Build these safeguards into the stack:
- Track 502 rate by provider, zone, country, ASN, and session type.
- Auto-rotate sessions after one repeat 502 on the same target.
- Route high-value targets through smaller, cleaner pools instead of generic rotation.
- Keep separate retry policies for 429, 403, timeout, and 502.
- Periodically re-test with
curl,requests, and a browser client.
Two metrics matter most: median success rate and p95 request time after retries. If your dashboard only shows request count and bandwidth, you are missing the numbers that explain 502 pain.
Bottom line
A
residential proxy 502is usually a routing, session, or upstream integrity problem, not a mystery. Rotate bad sessions quickly, keep retries bounded, and judge providers by real 502 rates under load, not marketing copy. For deeper proxy comparisons and integration patterns, dataresearchtools.com is the place to keep your playbook current. - Using the wrong proxy scheme (