Documentation Python quickstart Blog Free tools hello@quanticdata.ioLog in

Headless Browser Scraping: 53 Targets Measured

Verdicts for 53 sites fetched with and without a headless browser through residential proxies, 26 to 28 September 2026: browser required on 15, render optional on 4, render useless on 14, render returns fewer words on 12, collector needed on 8
Verdicts for 53 sites fetched with and without a headless browser through residential proxies, 26 to 28 September 2026: browser required on 15, render optional on 4, render useless on 14, render returns fewer words on 12, collector needed on 8

Headless browser scraping earns its price on 15 of the 53 sites we measured and costs words on 12. Between 26 and 28 September 2026 we fetched every target through a residential exit twice, as a plain HTTP client and fully rendered, and counted the words each view returned. Fifteen sites need the browser, four gain a little from it, fourteen gain nothing for up to 15 times the bytes, twelve return fewer words rendered than plain, and eight return no rows in either mode and want a collector. The table below has all 53 with the setting for each.

The search results teach how to render; none of them say where

The first page for "headless browser scraping" is tutorials and listicles: Selenium, Playwright and Pyppeteer walkthroughs, rankings of browsers, and a Reddit thread from r/webscraping whose title is the real question: headless browsers are killing my wallet, render or not to render? The poster runs a browser on every page of thousands of domains and wants a rule to decide per site. The top tutorial puts self-hosted browser infrastructure at 200 to 500 MB per instance and 200 to 800 dollars a month, and still opens a browser for every example.

Google's own documentation describes the same split from the crawler's side: Googlebot fetches the HTML first, queues the page for rendering, and indexes the rendered result later, which is why a page that only exists after JavaScript is a page the crawler sees late. A scraper has the same two phases and the same choice. What nobody on the first page does is fetch the page both ways and count. So the rest of this post is the count.

Fifteen sites need the browser, twenty-six do worse or no better with it

Each row was audited from the exit country in the second column, as a pure HTTP client with no JavaScript and then fully rendered, in one call. The words are the extractable body text of the home page or the public page named in the per-target post. Verdicts are on the measured word delta; the setting column is what to buy, and the two disagree on a handful of rows where the head of the page or a JSON endpoint carries the fact you want, which the setting says.

VerdictSitesWhat it means
Browser required15The plain fetch returns 0 to 463 words and the render multiplies it: bet365 0 to 987, Trustpilot 19 to 3,588, Deliveroo 194 to 2,247, Target 317 to 2,163.
Render optional4Plain HTTP returns most of the page: Walmart 2,190 of 2,975 words, Ticketmaster 494 of 1,021, with canonical and JSON-LD.
Render useless14The render adds under 2 percent or nothing: Shopee identical to the byte, Best Buy one word fewer for 9.8x the bytes, Shopify +4, Lazada +9.
Render loses words12The browser returns less than the plain client: Steam 2,802 to 1,396, Indeed 2,394 to 683, Glassdoor 624 to 54, Zillow 759 to 0, Etsy 678 to 0, Idealista 1,180 to 0.
Collector needed8Neither mode returns rows: Amazon 0 and 0, eBay 24 and 24, Booking.com 26 and 0, Skyscanner 0 and 0.

Two counts matter for a budget. Twenty-six of 53 sites, the useless and the losing rows together, are places where the browser is a cost with no return or a negative one. Fifteen are places where skipping it means missing the page. The remaining twelve are optional renders and collector cases. The rule that falls out of that is not "render when in doubt"; it is "fetch plain first, render on evidence", and the evidence is the table.

All 53 targets, one line each

The last column is the setting: network, fetch mode, exit, and the collector with rows and seconds from a run we made. Collector prices are per delivered row; the browser fetches cost bandwidth and time, both measured.

TargetExitPlain HTTP, wordsRendered, wordsVerdictThe setting
SteamUS2,8021,396No browser, the render loses wordsResidential US, plain HTTP: 2,802 words; prices from the appdetails JSON with cc=; never render, it halves the page
WalmartUS2,1902,975Render optionalResidential US, plain HTTP: 2,190 words with canonical and JSON-LD; the render costs 7.5x the bytes
LinkedInUS1,9282,588No browserResidential US, plain HTTP: follower count and Organization JSON-LD in the head; the render removes words
PayPalUS1,693n/aNo browserResidential, plain HTTP: 1,693 words; the real job is a static ISP IP for the Payflow allowlist
ShopeeSG1,4321,432No browserResidential SG, plain HTTP: 1,432 words, identical when rendered; never an Indonesian exit
LazadaSG1,1981,207No browserResidential SG, plain HTTP: 1,198 words; the render adds 9 words for 3.9x the bytes
IdealistaIT1,1800No browser, the render returns nothing usableResidential IT, plain HTTP: 1,180 words in 3.8 s; never render (0 words); listings via idealista_search, 10 rows in 5.5 s
AutotraderGB1,1131,129No browserResidential GB, plain HTTP: 1,113 words; the render adds 16; autotrader_search covers the US site, 10 rows in 15.3 s
RakutenJP8851,029No browserResidential JP, plain HTTP: 885 words, identical from the US; catalogue via the official Ichiba Item Search API
Pop MartUS841867No browserResidential US, plain HTTP: 841 words; product pages are no-store, poll them; never render
Shopify storesUS772776No browserRotating residential, plain HTTP: /products.json?limit=250 on any storefront, 250 products per call
EtsyUS6780No browser, the render returns nothing usableResidential US, plain HTTP with a browser TLS profile: 678 words in 205,911 bytes; never render (0 words); never an EU exit
DraftKingsUS647642No browser, the render loses wordsResidential US, plain HTTP, never render: 647 words plain, 642 rendered; one account per person in their terms
OKXDE623667No browserResidential, plain HTTP, exit pinned: DE 623, SG 464, US 371 words; public ticker in 364 bytes
RedditUS5740No browser, the render returns nothing usableResidential US, plain HTTP for listings: 574 words; comments via reddit_comments, 20 rows in 7.9 s; never render
SubitoIT602848Render optionalResidential IT, plain HTTP: 602 words in 183 KB; listings via subito_search, 10 rows in 2.7 s
AliExpressUS5382,628Browser requiredResidential, rendered for home and categories: 2,628 words against 538; listings via aliexpress_search, 20 rows in 4.5 s
KleinanzeigenDE512903Render optionalResidential DE, plain HTTP: 512 words with JSON-LD; listings via kleinanzeigen_search, 10 rows in 3.5 s
TicketmasterUS4941,021Render optionalResidential US, plain HTTP: category pages carry MusicEvent JSON-LD; prices from the Discovery API
NetflixUS4631,204Browser requiredResidential, plain HTTP, one exit per market: 463 words with the prices ($8.99 US, £7.99 GB, 6,99 € DE); never render
TargetUS3172,163Browser requiredResidential US, rendered: 317 words plain, 2,163 rendered; store and ZIP follow the IP, pin the state
Best BuyUS285284No browserResidential US, plain HTTP: 285 words from the edge cache; the render costs 9.8x the bytes for one word fewer
ZalandoIT266275No browserResidential IT, plain HTTP: 266 words; catalogue with prices via zalando_search, 10 rows in 3.6 s
VintedIT230217No browser, the render loses wordsResidential IT, plain HTTP: 230 words; the render loses 13; the locale is the domain, not the exit
StubHubUS0157Browser requiredResidential US, rendered through the web scraping API at $0.001 per page: 0 words plain, 157 rendered
bet365 (UK exit)GB0987Browser requiredResidential, rendered, exit pinned to the market you read: 987 words from the United Kingdom
bet365 (DE exit)DE0149Browser requiredSame URL from a German exit: 149 words, a different licensed catalogue, not a translation
InstagramUS4040No browserResidential US, plain HTTP: the counts are in the head (104M followers); the render adds nothing
TaobaoSG3656CollectorResidential SG, plain HTTP on /lang/ and item pages (410 words), not the home (36); no collector
BinanceDE261,196Browser requiredPlain HTTP on data-api.binance.vision from any exit, 558 bytes per ticker; one static ISP IP per API key
Booking.comIT2626CollectorNeither fetch mode (26 words): booking_stays, 20 priced properties in 5.1 s
YouTubeUS15585Browser requiredResidential US, plain HTTP: the head resolves @handle to the channel ID; videos via youtube_channel, 30 rows in 3.8 s; EU exit lands on consent
TikTokUS512CollectorNeither fetch mode (5 and 12 words): the TikTok profile collector
FacebookUS0350Browser requiredResidential US, rendered for Page text (350 words); the follower count sits in og:description without a browser; a DE exit rewrites the number separators
RobloxUS0128Browser requiredResidential US, plain HTTP on game pages (213 words) and the games.roblox.com JSON; never render, 4.4 MB for 128 words
SpotifyUS014CollectorWeb API with client credentials for the catalogue; plain HTTP only on the spotify.com price pages; never render open.spotify.com
TwitchUS0125Browser requiredResidential, plain HTTP on channel pages: JSON-LD with 2,461,147 followers in 214 KB; the Helix API for data; never render
AmazonUS026CollectorNeither fetch mode (2,007 bytes, 0 words): amazon_search, 20 products in 43 s at $0.001 each
eBayUS2424CollectorNeither fetch mode (1,976 bytes, 24 words): ebay_search, 25 listings in 19.5 s; the run declares its exit
Pokemon CenterUS1,622765No browserResidential US, plain HTTP: 1,622 words; the render returns 765 in 62 s; resale prices via ebay_search
IndeedUS2,394683No browser, the render returns nothing usableResidential US, plain HTTP with a browser TLS profile: 2,394 words in 601 KB on the first request; rows via indeed_jobs, 10 in 7.3 s
ZillowUS7590No browser, the render returns nothing usableResidential US, plain HTTP: 759 words, price, beds and square feet in the meta description; never render; zillow_search, 20 rows in 3.0 s
TripadvisorUS7130No browser, the render returns nothing usableResidential US, plain HTTP: 713 words with 19 LocalBusiness JSON-LD blocks; never render; tripadvisor_search, 30 rows in 8.1 s
GlassdoorUS62454No browser, the render loses wordsResidential, plain HTTP: 624 words US, 589 GB, with JSON-LD; never render, it lands on the login form; salaries via indeed_jobs
TrustpilotUS193,588Browser requiredResidential, rendered with a 6 s wait: 3,588 words on the home, 4,389 on a company page, 19 plain; reviews via trustpilot_reviews, 10 in 14.8 s
AirbnbUS5947CollectorPlain HTTP gives 59 words: airbnb_stays, 18 stays with the nightly price in 5.3 s; a DE exit gets a redirect stub
DeliverooGB1942,247Browser requiredResidential GB, rendered: 2,247 words against 194; the full menu exists only in the browser
DoorDashUS48426No browser, the render returns nothing usableResidential US, plain HTTP: 484 words on the first request; never render; doordash_restaurants, 50 rows in 6.0 s
Uber EatsUS99206Browser requiredResidential US, rendered for restaurant pages (206 words against 99); the home is thin in both modes
KayakUS2,4492,564No browserResidential US, plain HTTP: 2,449 words with FAQPage JSON-LD; a GB exit redirects to kayak.co.uk; fares via google_flights, 15 in 19.4 s
ExpediaUS7214No browser, the render returns nothing usableResidential US, plain HTTP: 72 words with h1 and canonical; never render (14 words); rates via hotels (20 rows) and google_flights (15 in 19 s)
SkyscannerGB00CollectorNeither fetch mode (0 words in both): google_flights, 15 LHR to JFK fares in 33.7 s
bet365 (US exit)US02,031Browser requiredSame URL from a US exit, rendered: 2,031 words; three licences, three catalogues

Where the browser earns its price

The fifteen required rows share one shape: the plain fetch returns a head and a shell, and the rendered page is where the copy lives. bet365 is the extreme: 0 words plain from every exit, then 987 rendered from the United Kingdom, 149 from Germany and 2,031 from the United States, three licensed catalogues behind one URL, so the exit is part of the setting. Trustpilot goes from 19 words to 3,588 with a six-second wait before capture. Deliveroo multiplies by 11.6, 194 to 2,247, because the menu exists only in the browser. Target goes 317 to 2,163 and assigns store and ZIP from the IP, so the state is pinned too.

Four of the fifteen carry a required verdict and a plain-HTTP setting, and the table says so. On Netflix the render returns 1,204 words to the plain client's 463, but the 463 include the prices per market, which is the fact people fetch it for. On YouTube the head resolves an @handle to the channel ID and carries the subscriber count without a browser; on Twitch the channel page ships JSON-LD with the follower count in 214 KB; on Roblox the games JSON is 1,802 bytes where the render is 4.4 MB for 128 words. The verdict measures words. The setting measures what you needed.

Where the browser removes words

Twelve sites return fewer words rendered than plain, and the reasons are two. On four the page itself breaks under the render: Steam halves from 2,802 to 1,396 and its h1 becomes an error message, DraftKings loses five words, Vinted loses thirteen, and Glassdoor lands on its login form with a canonical of /member/profile/login and 54 words where the plain client got 624 with JSON-LD.

On eight the rendered view returns nothing usable while the plain client reads the page: Indeed 2,394 words plain against 683, Zillow 759 against 0, Etsy 678 against 0, Idealista 1,180 against 0, Tripadvisor 713 with 19 LocalBusiness objects against 0, Reddit listings 574 against 0, DoorDash 484 against 26, Expedia 72 against 14. On every one of these the setting is residential, engine: tls, sometimes with a browser TLS profile, and never a render. The common tutorial advice runs the other way: if the plain fetch looks thin, open a browser. On these eight it turns a working fetch into an empty one and doubles the bytes. The four shapes those empty replies take, and what to do with each, are in read the block and what to do.

Where the render is a tax

The fourteen useless rows are the ones that quietly cost the most, because nothing looks wrong. Best Buy returns 285 words plain and 284 rendered for 4,968,555 bytes against 506,484: 9.8 times the bandwidth for one word fewer. Walmart, an optional row, costs 7.5x the bytes for the last quarter of the page. Shopee returns 1,432 words in both modes, identical, for 1.7x the bytes. OKX costs 14.9x for 44 extra words. Roblox costs 43.7x. Over a gigabyte of residential Basic at $0.80, counting a gigabyte as 10^9 bytes, a rendered Best Buy home page costs $0.0040 and a plain one $0.0004; across a 10,000-page price watch that is 36 dollars a run spent on nothing.

The plain fetch is also faster on every row where we recorded both. Walmart's plain page arrives in 2.5 seconds from the edge cache and the render took 59.8 seconds; Booking.com's plain reply took 1.3 seconds and the render 46.7; Glassdoor's render took 22.9 seconds today to reach a login form. Time is the second cost of the browser, and on a pool it is the one that caps throughput.

Eight sites where neither mode returns rows

Amazon (2,007 bytes, 0 words), eBay (1,976 bytes, 24 words from the United States and from Germany), Booking.com (26 words plain, 0 rendered for 857,992 bytes), Skyscanner (0 and 0), Airbnb (59 and 47), Taobao's home (36 and 56), Spotify (0 and 14) and TikTok (5 and 12) are not thin sites. They are sites that do not serve the catalogue to an anonymous first request in any mode. The setting there is the collector, and today's runs are the proof: ebay_search returned 25 priced listings in 19.5 seconds, booking_stays returned 20 priced Rome properties in 5.1 seconds, and the per-target posts have amazon_search at 20 products in 43 seconds and google_flights at 15 fares in 33.7 seconds. The eight are compared row by row in when the collector wins.

The rule that replaces "render when in doubt"

The Reddit poster wanted a detector that works across thousands of domains with one page each. The 53 rows give one. Fetch plain first, through the web scraping API at $0.0002 per page, and read four fields of the reply: the word count, the canonical, the h1 and the JSON-LD types. Then:

plain = fetch(url, engine="tls")

if plain.words >= 200 or plain.jsonld:
    use(plain)                      # 30 of 53 rows: the page, or the fact in the head
elif plain.canonical and plain.h1 and plain.words < 200:
    r = fetch(url, engine="render") # 15 of 53: bet365, Trustpilot, Deliveroo, Target
    use(r if r.words > plain.words else plain)
elif plain.bytes < 5000 and not plain.canonical:
    use(collector(url))             # Amazon, eBay, Booking.com: no page exists to render
else:
    use(plain)                      # thin but real: Expedia, Airbnb head

The comparison in the second branch is the part the tutorials skip. Rendering once and keeping the view with more words is what catches Steam, Indeed, Glassdoor and Zillow, where the render returns less; it costs one browser fetch per new domain, not one per page. After the first pair the site's answer is known, and it holds: the four rows we repeated today returned the same shape as two days ago, eBay 24 words, Booking.com 26, Expedia 72 plain and a refusal rendered, Glassdoor's login canonical rendered.

The setting that works on the 53 targets

  • Network: residential, Basic line at $0.80/GB, for all 53. Nothing in the two passes scored the address on a page where the plain client read the page; where the plain client got a shell, the render from the same exit got the same shell. Premium at $2.20/GB and mobile at $2.30/GB bought no extra words anywhere in this table. ISP static IPs, from $2.50 per IP per month at volume, appear only where a platform keys an API to an address: PayPal's Payflow allowlist, Binance and OKX API keys.
  • Fetch mode: engine: tls on 30 of 53, with the word counts in the table; rendered on 15, of which bet365, Trustpilot, Deliveroo, Target, AliExpress and Facebook are the clear cases; a collector on 8. Where the head carries the fact (LinkedIn and Instagram follower counts, YouTube channel IDs, Twitch JSON-LD), the plain fetch is the setting whatever the word delta says.
  • Country: the market you read, pinned. The same URL returns 987, 149 and 2,031 words on bet365 from the UK, Germany and the US; Amazon from Germany is a different page at /-/de/; Etsy from an EU exit is 8 words; YouTube from the EU is a consent page; a German exit on Facebook rewrites 28,729,208 with dots and breaks a comma parser.
  • When the proxy is not enough: the collector named in the row, with the run we made: ebay_search 25 listings in 19.5 s, booking_stays 20 properties in 5.1 s, amazon_search 20 products in 43 s, indeed_jobs 10 in 7.3 s, zillow_search 20 in 3.0 s, reddit_comments 20 in 7.9 s. Where a render is the setting, the web scraping API with rendering at $0.001 per page, billed on success.
  • Failed requests are never billed, and every account gets $2 of free API usage per month: 10,000 plain fetches, or 2,000 rendered pages, or one plain-and-rendered pair on every site you care about before the first invoice.

Sources & further reading

FAQ

Quick answers on headless browser scraping.

Something else? Ask us →

How many sites actually need a headless browser for scraping?

Fifteen of the 53 we measured between 26 and 28 September 2026, where the plain fetch returns a shell and the render fills it: bet365 0 to 987 words, Trustpilot 19 to 3,588, Deliveroo 194 to 2,247, Target 317 to 2,163. Twenty-six do worse or no better with a browser, four gain a little, and eight return no rows in either mode and need a collector. Four of the fifteen still get a plain-HTTP setting because the head or a JSON endpoint carries the fact you want.

Can a headless browser return less than a plain HTTP request?

Yes, on 12 of 53 sites. Steam drops from 2,802 words to 1,396 and its h1 becomes an error message; Indeed drops from 2,394 to 683; Glassdoor from 624 to 54 on a login form; Zillow, Etsy, Idealista and Tripadvisor go from 759, 678, 1,180 and 713 words to 0. On every one of those the setting is residential with engine tls and no render. Rendering once per new domain and keeping the view with more words catches all twelve.

How much more does a rendered page cost than a plain fetch?

On bandwidth, between 1.3x and 44x on the rows where we weighed both: Best Buy 9.8x for one word fewer, Walmart 7.5x, OKX 14.9x, Roblox 43.7x, Booking.com 216x for zero words. At $0.80/GB, counting a gigabyte as 10^9 bytes, a rendered Best Buy home page is $0.0040 against $0.0004 plain. On time, Walmart plain arrives in 2.5 seconds and rendered in 59.8; Booking.com 1.3 against 46.7. Through the web scraping API the two prices are $0.0002 and $0.001 per page.

What is the rule for deciding whether to render a page?

Fetch plain first and read four fields: words, canonical, h1, JSON-LD types. 200 or more words, or any JSON-LD, means use the plain page (30 of 53 rows). A canonical and an h1 with fewer than 200 words means render once and keep whichever view has more words (the 15 required rows, and the safety net for the 12 where the render loses). Under 5,000 bytes with no canonical means no page exists to render and the collector is the setting (Amazon, eBay, Booking.com). One rendered fetch per new domain, not per page.

Does the exit country change whether a site needs the browser?

It changes what the browser returns more than whether you need it. bet365 renders 987 words from the United Kingdom, 149 from Germany and 2,031 from the United States on one URL, three licensed catalogues. Amazon from a German exit is a different page at /-/de/ with 546 words where the US exit gets 0. Etsy from an EU exit returns 8 words against 678 from the US. YouTube from the EU lands on a consent page. Pin the exit to the market you read, in both fetch modes.

Which sites return nothing in either fetch mode?

Eight: Amazon (2,007 bytes, 0 words), eBay (1,976 bytes, 24 words from the US and Germany alike), Booking.com (26 words plain, 0 rendered), Skyscanner (0 and 0), Airbnb (59 and 47), Taobao home (36 and 56), Spotify (0 and 14) and TikTok (5 and 12). The setting on those is the collector: on 28 September 2026 ebay_search returned 25 priced listings in 19.5 seconds and booking_stays returned 20 priced properties in 5.1 seconds, billed per delivered row.

Fetch it plain, then render on evidence

The 53 verdicts above came from one tool: fetch any URL as a plain client and as a browser, compare the word counts side by side, and buy the render only where it returns more. Every account gets $2 of free API usage per month, and failed requests are never billed.

Related reading

Proxies12 Sites Where Headless Browsers Lock You Out

Twelve of the 53 sites we measured in September 2026 give a headless browser less than they give a plain HTTP client, and seven of them give it nothing. The same twelve URLs return 11,157 words over plain HTTP and 3,032 rendered. Steam, Etsy, Idealista, Reddit, Indeed, Zillow, Tripadvisor, DoorDash, Expedia, DraftKings, Vinted and Glassdoor, with the numbers, the cost of the browser you do not need, and the collector rows for the pages the fetch cannot reach.

Read →
ProxiesGeo-Targeted Proxies: 987 Words UK vs 149 DE

The same URL, rendered through residential exits: 987 words from the United Kingdom, 149 from Germany, 2,031 from the United States. Nothing was translated; each exit landed on a different licensed product. On 18 of the 53 sites we measured, geo-targeted proxies change the page itself: the domain on AliExpress, the entity on OKX, the price line on Netflix, the number format on Facebook and LinkedIn, and whether the channel page exists at all on YouTube. Pin the exit per job or you are comparing two different pages.

Read →
ProxiesWeb Scraping API vs Proxy: 25 eBay Rows, 19 s

Web scraping API vs proxy is the wrong question on eight of the 53 sites we measured. On Amazon, eBay, Booking.com, Skyscanner, Airbnb, Expedia, Taobao and Spotify the page a proxy fetches holds between 0 and 72 words in either fetch mode. On 28 September 2026 the ebay_search collector returned 25 priced listings in 19.5 seconds and booking_stays returned 20 priced Rome properties in 5.1 seconds. The table, the cost per row and the setting for each site.

Read →