Use case

Proxies for Botasaurus: a list rotates, a login starts a Node process

Rotate proxies in Botasaurus: how a list, a function and a string differ, and why a credentialed address loads proxy-chain through a JavaScript bridge.

HProxy Team··Updated September 20, 2026·5 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

Botasaurus puts a proxy on both of its decorators, the browser one and the plain request one, with the same argument in both. That part is pleasant. What is not documented is how it treats a list, how that differs from a list your own function returns, and what an address with a login quietly starts on your machine. We read all three of its packages on 20 September 2026.

One version note first: this project publishes no releases and no tags at all, so the head of the main branch is the only version there is. We read it at commit 6c9260de, dated 26 July 2026.

The three shapes

from botasaurus.browser import browser

@browser(proxy="http://GATEWAY_HOST:GATEWAY_PORT")
def scrape(driver, data):
    ...
What you passWhat each task gets
A stringthat address, every time
A listthe next address, cycled in order
A function returning a stringwhatever it returns for that item
A function returning a listone entry, chosen at random

The last two rows are the trap. The same list behaves differently depending on where you put it: handed to the decorator it becomes an endless cycle and rotates predictably, while a list that comes back from your function reaches a small helper that picks one at random.

Neither is wrong. They are simply different, and only one of them is what most people mean by rotation. If you want predictable round robin, pass the list directly.

Both decorators use the same three lines for this, so moving a task between a browser and a plain request does not change the behaviour.

What a login starts

When the address carries a user name and password, the driver starts a local proxy and passes the browser that local address instead. Your login never reaches the browser, which is the standard answer to the fact that a browser cannot take one.

Here is the part worth knowing. That local proxy is not Python. The helper loads a Node package through a Python to JavaScript bridge and asks it to anonymise your address:

chain = require("proxy-chain")   # loaded through a JS bridge, from Python

So a Python scraper with a credentialed proxy is also running a Node process. When the address has no login, the helper checks that first and hands the address straight to the browser. No bridge, no Node, no extra process.

That explains two reports on its tracker that otherwise look unrelated: a timeout when the library runs inside a background worker, and a proxy that stops working once the program is compiled into a single binary. Both are the same dependency, met in two places where a Node runtime is awkward.

Rotation and browser reuse

The address is chosen when a browser is created. The library can also reuse browsers between tasks, which is good for speed and directly at odds with rotating per task: a reused browser keeps the address it was started with. Its tracker has an issue on exactly this.

So pick one. Rotate per task and let each task start its own browser, or reuse browsers and accept that the address is per browser.

Which proxy type fits it?

Residential, for the sites that refuse a hosting address. In our paired test a residential address changed 4 of 13 answers, while four sites refused both. The stealth features exist for those four; the address is for the rest.

Then, specifically for this library, consider an allowed address. On an HProxy Residential Premium plan your machine's address can be allowed, up to 150 per plan, so the address carries no login. With most tools that is a tidiness argument. Here it removes a moving part: no local proxy, no bridge, no Node process, and none of the two failures above. That is a real reason to prefer it, and it comes from their code rather than from our sales page.

If you do want a list of ports to rotate through, pass them as a list to the decorator and let each task take the next one. A retry is still worth writing, since 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

  • An authenticated proxy does nothing. Several reports across 2024. Check that the Node side is available at all.
  • It works in a script and fails in a worker. The bridge again.
  • It works locally and fails compiled. The bridge again. An allowed address avoids it.
  • Rotation has no effect. You are reusing browsers, so the address is fixed per browser.
  • Rotation is not in the order you expect. Your function returned a list, which is picked at random.
  • 407 Proxy Authentication Required. The login is wrong. Our 407 guide covers it.

What this page does not cover

We read three repositories as text and ran none of them, so we did not watch the local proxy start, did not time the bridge, and did not reproduce the worker or compiled binary failures. The rotation behaviours are read in the source and are documented nowhere, which is precisely the kind of thing that can change quietly. Because the project publishes no releases, two installations made on different days can differ. We will read the proxy branches again by 20 October 2026.

Where to go from here

Proxies for Crawlee covers a scraper that starts the same local proxy, from Node where it belongs. Proxies for Steel Browser does it a third time, and also counts the bytes that used your line. Proxies for Patchright covers the other Python stealth browser, where the proxy option is inherited untouched.

Sources

  • The proxy argument and the list cycle in both decorators (botasaurus/browser_decorator.py, botasaurus/request_decorator.py), the random pick for a list returned from a function (botasaurus/decorators_common.py), and the documented example (docs/docs/what-is-botasaurus.md). omkarcloud/botasaurus at commit 6c9260de, 26 July 2026, read 20 September 2026.
  • The local proxy and the browser argument (botasaurus_driver/core/config.py). omkarcloud/botasaurus-driver at commit db1d2916, 30 July 2026.
  • The authentication helper, its check for a login and the JavaScript bridge. omkarcloud/botasaurus-proxy-authentication, read 20 September 2026.
  • Issues 109, 113, 114, 171, 193 and 264 on authentication, SOCKS, the worker timeout, rotation with browser reuse, and compiled binaries. Botasaurus issue tracker, read 20 September 2026.
  • Our paired address test of 19 September 2026. Raw output is kept in the research folder of our OpenClaw page.
  • Plans, allowed addresses and sticky sessions. HProxy documentation, hproxy.com/docs, 20 September 2026.

Frequently asked questions

How do I give Botasaurus a proxy?
Pass proxy to the browser or request decorator. It takes a plain string, a function that receives the item being processed, or a list of addresses.
Does a list rotate?
Yes, in order. A list passed to the decorator is cycled, so each item takes the next address. A list returned by your own function is different: that one is picked at random.
What happens when the address has a username and password?
The driver starts a local proxy and gives the browser that local address, so the browser never sees your login. That local proxy is a Node package, loaded from Python through a bridge.
Why does my proxy fail in a worker or a compiled binary?
Both are reported on its tracker, and both point at that Node dependency. An address without a login skips it entirely.
Can I rotate with a reused browser?
Not within one browser. The address is chosen when the browser starts, so a reused browser keeps the address it was created with.

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