Use case

Proxies for puppeteer-extra: the stealth plugin does not hide your address

Proxies in puppeteer-extra: what the stealth plugin covers, the language default that fights your exit country, and the routing plugin that bills by host.

HProxy Team··Updated September 20, 2026·6 min read
HProxy.Use case

Free proxies won't hold up here.

Shared datacenter IPs get flagged and dropped fast. When it has to hold, gaming, streaming, accounts, you need mobile and residential IPs that read as a real device, from $0.44/GB, pay as you go.

See plans & pricing

The stealth plugin is the most recommended answer to being blocked in Node. It is also the most misunderstood one, because it does nothing at all about where your traffic comes from. We read the repository on 20 September 2026, and there is a second plugin in it that almost nobody links.

A date first, because the recommendations rarely carry one. The packages were last published on npm in March 2023. The repository was last pushed to in July 2024. It still works. Nothing in it has moved in a long time.

What the stealth plugin covers

The plugin is a bundle of seventeen small patches. Each one fixes a way that a headless Chrome differs from a normal one:

The names of the evasions are the evidence. They are chrome.app, chrome.csi, chrome.loadTimes, chrome.runtime, defaultArgs, iframe.contentWindow, media.codecs, navigator.hardwareConcurrency, navigator.languages, navigator.permissions, navigator.plugins, navigator.vendor, navigator.webdriver, sourceurl, user-agent-override, webgl.vendor and window.outerdimensions.

There is no WebRTC evasion. There is no timezone evasion. There is no geolocation evasion. The plugin makes a browser look less automated, which is a real and useful job, and it is not the job of looking like it comes from somewhere.

Two evasions that argue with your proxy

The fourth row of that chart needs a footnote, because the plugin does set your language and its default can work against you.

Two evasions announce it. navigator.languages falls back to ['en-US', 'en']. The user agent evasion sets the Accept-Language header and the same property, with a documented default of en-US,en. Both run on every page.

So route through Germany with default settings, and every request says en-US while the address says Germany. That is a contradiction a site can read without doing any work at all.

The fix is documented, in a comment inside one evasion. Take that evasion out of the bundle and add it back with a locale:

const stealth = StealthPlugin()
stealth.enabledEvasions.delete('user-agent-override')
puppeteer.use(stealth)

const UserAgentOverride = require('puppeteer-extra-plugin-stealth/evasions/user-agent-override')
puppeteer.use(UserAgentOverride({ locale: 'de-DE,de' }))

One more warning from the same file, worth repeating: calling page.setUserAgent() yourself resets the language and platform values this evasion set.

The same repository ships @extra/proxy-router, a plugin for both puppeteer-extra and playwright-extra whose whole job is proxies. Not one of the six rival articles we read for this page mentions it.

What it offers, in their words: it handles proxy authentication, takes several proxies at once, routes by host or domain, changes proxies after the browser has launched, and collects traffic stats per proxy or per host.

It works the way three earlier tools in this series do. It starts a local proxy server, points the browser at that, and relays onward to the real address while answering the upstream login. The library underneath is the same one Crawlee uses. That pattern is now the standard answer to Chrome refusing a login in a launch flag.

Routing by host

Configure the addresses as a dictionary of names, then write one function. It receives a host and returns a decision:

Return valueWhat happens
a proxy namethat address is used for this host
DEFAULT, null or nothingthe default address is used
DIRECTno proxy, the request goes out normally
ABORTthe request is cancelled

One caveat from their own documentation: the browser usually makes a single proxy connection per host, so the decision is per host rather than per request.

Where the bytes went

The interesting part is the accounting. The plugin reports bytes per proxy and per host, and their own documented example says more about browser traffic than any argument we could write:

LaneBytes it carried
The datacenter line, carrying map tiles441,734
The default line125,823
Direct connections100,457
The residential line4,764
Blocked hosts0

That is a run where the expensive address carried under five kilobytes and a pile of map tiles cost nearly half a megabyte somewhere cheap. On a per gigabyte line that difference is the entire bill.

Which proxy type fits it?

Residential, for the sites that answer a hosting address differently. Our own test is the size of that effect: 4 of 13 answers changed between a server address and a residential one, with plain requests and no browser involved.

The routing plugin makes the cost argument easy here. Put the residential line on the hosts that matter, send fonts, tiles and advertising scripts direct or to a cheaper address, and block what you do not need at all. The byte table above is that idea already measured by the author.

An allowed address is worth considering on a server, because then no password sits in a plugin configuration: on a Residential Premium plan your machine's address can be allowed, up to 150 per plan. A sticky port suits a run that works through one site, with a retry in your code because a sticky address can change early when its device leaves the network. The residential proxies page lists the plans, and the plan API manages allowed addresses from code.

What breaks

  • Stealth is on and you are still refused. The plugin never changed your address. Check what the site sees.
  • Your proxy country and your browser disagree. The language defaults to en-US in two places. Set the locale.
  • You set a user agent yourself and the locale reverted. That call resets what the evasion did.
  • Only one address is in use. The launch option takes one. Several addresses need the routing plugin.
  • The traffic bill is larger than the page count. Route the heavy hosts somewhere else, or block them.

What this page does not cover

We read the repository and the registry as text and did not install or run anything, so we did not test the stealth plugin against a detector, did not start the routing plugin, and did not reproduce its byte table. Those numbers are the author's documented example, not our measurement. We read the evasion listing, two evasions, the routing plugin's documentation and its dependencies closely, and we did not read the router's implementation. We did not establish whether the stealth plugin still works against current detectors, which is the question its age raises. We will look again by 20 December 2026.

Where to go from here

Proxies for Crawlee covers the same local forwarder pattern in a crawler that also rotates addresses by tier. Proxies for Camoufox covers a browser that looks up the exit address and aligns the timezone and language with it, which is the job this plugin leaves to you. Proxies for PinchTab covers a tool that treats the proxy as validated configuration rather than a launch flag.

Sources

  • The stealth plugin's evasion directory, the language evasion and its default, the user agent evasion with its Accept-Language default and the documented way to pass it options. berstend/puppeteer-extra, head of master, read 20 September 2026. The repository has no releases and no tags.
  • The routing plugin: its feature list, how it works, the routing function's return values, the traffic statistics and the example output, and its dependency on the local forwarder library. packages/plugin-proxy-router, published as @extra/proxy-router 3.1.6.
  • Publish dates for puppeteer-extra 3.3.6, puppeteer-extra-plugin-stealth 2.11.2 and @extra/proxy-router 3.1.6, all 1 March 2023. npm registry, read 20 September 2026.
  • Our paired address test of 19 September 2026: 16 URLs, plain requests, two runs from our server and two through a residential line of our house plan. Raw output is kept in the research folder of our OpenClaw page.
  • Plans, allowed addresses and per gigabyte pricing. HProxy documentation, hproxy.com/docs, 20 September 2026.

Frequently asked questions

Does puppeteer-extra-plugin-stealth hide my IP address?
No. It has seventeen evasions and none of them touches the network path. It changes what the browser says about itself, never where the request comes from.
Does the stealth plugin stop a WebRTC leak?
No. There is no WebRTC evasion in the plugin. If that path matters to you, it has to be handled outside this plugin.
Why does my German proxy still look English?
Two evasions announce a language and both default to en-US. Remove the user agent evasion from the default set and add it back with a locale such as de-DE,de.
Can I use a different proxy per domain?
Yes, with the routing plugin in the same repository. A function receives the host and returns a proxy name, DIRECT for no proxy, or ABORT to block the request.
Is puppeteer-extra still maintained?
The packages were last published in March 2023 and the repository was last pushed to in July 2024. It still works, but nothing in it has moved for a long time.

Proxies that don't die mid-job

Residential, ISP, datacenter and mobile, verified by the same engine that runs tens of millions of checks. They read as a real device and hold up under load. Pay as you go, and your balance never expires. $0.44/GB is the 2,000 GB+ rate; a single gigabyte is $0.50/GB, with no minimum order.

129M+ proxy checks run · 100+ countries · HTTP / HTTPS / SOCKS · re-checked every few minutes · no signup

HProxy.

Honest guides and comparisons on proxies, scraping and staying unblocked, from the team that runs the network.

RSS feed