ScalebrowserDOCS

Proxies & exits

Store a proxy, check it, and understand the exit rule: how one bought gateway becomes many stable addresses, why an address belongs to one profile, and what the guard does while a browser runs.

Where a request comes from is judged before any JavaScript on the page has run, so nothing the browser does reaches it. This page is the half of a profile's identity that lives outside the browser.

Storing one

A proxy is a row: kind, host, port, optional credentials, a rotation setting and a label.

bash
$ curl -X POST http://127.0.0.1:8787/v1/proxies \
    -H "Authorization: Bearer $SCALEBROWSER_BEARER_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"kind":"gateway","host":"gw.dataimpulse.com","port":823,
         "username":"…","password":"…","rotation":"rotating","label":"DE mobile"}'
FieldValuesNotes
kindhttp · socks5 · gatewaygateway is a provider endpoint that hands out exits, rather than one exit.
rotationsticky · rotatingWhat the provider does. This is your claim about them, not a measurement.
labelfree textGive one. A whole pool shares host, port and kind, so nothing else tells two rows apart.

Checking one

Two calls, and the difference matters.

CallWhat it does
POST /v1/proxies/:id/checkRuns the real check through a saved proxy: reachability, exit address and country, and the fingerprint verdict. Stores the result and emits a proxy_checked event.
POST /v1/proxies/checkThe same check on an unsaved configuration. Stores nothing, emits nothing, and adds latency_ms. Test before you persist.

An unreachable proxy is reported as healthy: false, not as an error. The row exists; it just does not work right now.

One gateway, many profiles

A residential or mobile pool is bought once and split into many stable exits by a session tag, a value the provider reads out of your username or password. The daemon knows the spelling for fourteen providers and writes the tag for you, so one bought account serves many profiles with a different address each.

Provider hostWhere the tag goesShape
brd.superproxy.iousernameup to 20 alphanumerics
pr.oxylabs.iousernameup to 20 alphanumerics
residential.proxy.decodo.comusernameup to 20 alphanumerics
proxy.soax.comusernameup to 32 alphanumerics
gw.netnut.netusername8 digits
p.webshare.iousername6 digits
rp.scrapegw.comusernameup to 20 alphanumerics
gw.dataimpulse.comusernameup to 20 alphanumerics
unmetered.residential.proxyrack.netusernameup to 20 alphanumerics
pool.infatica.iousernameup to 16 alphanumerics
geo.iproyal.compasswordexactly 8 alphanumerics
rp.evomi.compasswordup to 16 alphanumerics
residential.rayobyte.compasswordup to 16 alphanumerics
superproxy.zenrows.compasswordup to 16 alphanumerics

The host is matched on its ending, so a regional hostname such as de.gw.netnut.net resolves too.

An unknown host is not an error. The daemon leaves the credentials exactly as you entered them and simply cannot draw a new session. Guessing a spelling would be worse than not trying: a malformed username is a refused connection at most gateways, which reads like a dead proxy.

One address, one profile

Two of your profiles arriving from the same address at the same site is the cheapest link there is. The daemon therefore treats an exit address as owned.

When a profile starts and the address it draws already belongs to another profile, the daemon draws a new session tag and tries again, up to five times. If every draw is taken, the start is refused with error 4013, which is deliberately not 4002: this is not a proxy problem, and sending you to check your proxy would send you looking for something that is not there.

The comparison unit

Not the raw string. For IPv4 it is the address; for IPv6 it is the /64 prefix, because a subscriber line draws new addresses out of that prefix at will, and comparing whole IPv6 addresses would report "different" for every pair while protecting nothing.

Two different addresses inside one IPv4 /24 count as neighbours. That is advisory by default and can be made blocking.

How long ownership lasts

By the kind of address, because a mobile address is recycled in days and a datacenter address is not:

Address kindOwnership lasts
mobile3 days
residential30 days
datacenter90 days
unknown30 days

unknown deliberately takes the middle term rather than the longest. A deployment without an address dataset classifies everything as unknown, and the longest term there would drain the pool while looking careful.

The guard, while a browser runs

An exit can change under you: a provider rotates, a session times out, a route flaps. Two beats watch for it:

  • Keep-alive, every 30 seconds, only where the provider documents an idle cut-off. A couple of hundred bytes that say nothing and hold the session. Oxylabs, Decodo and SOAX drop a session after 60 seconds of silence, Bright Data after five minutes, so a resting profile would otherwise lose its address between two clicks.
  • Address check, every 120 seconds. The real question, and the only one that can cut a wire.

The verdict rides on the event stream as exit_guard_changed, in one of four states:

StateWhat it means
okThe address is the one this profile owns.
degradedOne or two probes in a row got no answer. Nothing is cut.
unverifiedThree in a row got no answer. Still nothing is cut: the wire is unverified, not proven wrong.
severedThe address moved onto one another profile owns. The wire is cut, and stays cut.

A silent probe is not an address change. If it were, one unreachable probe endpoint would sever every healthy profile behind it, and the outage would cause exactly the damage the guard exists to prevent. degraded and unverified are statements about our knowledge, and neither cuts anything.

A severed wire is not reconnected automatically either, because an automatic return would show the page a second address change mid-session.

What the promise actually is

A number, not the word "never". The relay opens its own upstream per browser connection, so between a provider-side change nobody announced and the next check there is a window by construction:

  • zero at start, measured live rather than read off a stored field
  • 30 seconds around a rotation whose period two matching gaps have confirmed
  • at most 120 seconds otherwise

The rotation shape is measured, with two probes, and never read off the row's rotation setting: that field is a customer's claim about a provider, and the provider is the one that decides.

Turning the rule off

GET and PUT /v1/exit-rule read and set it for this machine, and the management app has the switch under Settings. Off means starts are never refused for a taken address and nothing is watched.

That is a real choice for a single-profile setup and a bad one for a fleet.

What the daemon deliberately does not do

It does not rewrite traffic. There is no man in the middle, no header injection, no certificate of ours in the chain. A proxy is a proxy, and the coherence work happens inside the engine where a page can be told the truth instead of a rewritten version of it.

A datacenter exit therefore stays a datacenter exit. No patch in the browser reaches that, which is why sharp targets presuppose a terminating residential or mobile proxy. See Coherence & proxies.

Next

  • Coherence & proxies: what the exit is compared against before a launch.
  • Profiles & personas: the half of the identity that lives inside the browser.
  • Events: the exit_guard_changed and proxy_checked frames.
  • Errors: 4002 and 4013, and why they are different.