How the gateway works
The steps a request passes through between your client and the target site, and what can reject you at each one.
Knowing the shape of this chain saves a lot of guessing later — most "it won't connect" reports are stuck in the first three steps and have nothing to do with the target site.
The path of one request
TCP connection
Your client connects to GATEWAY_HOST:58971. The gateway applies identity-independent protections first: total connection count, per-source-IP concurrency, new-connection rate.
Rejections at this layer simply close the socket. There is no HTTP status code to read.
Protocol detection
The gateway peeks at the first byte. 0x05 means a SOCKS5 handshake; anything else is parsed as HTTP (CONNECT or ordinary forward).
One port serves both protocols, so "wrong port" is not a failure mode here.
Username option parsing
The username is split on - and scanned from the second segment for the first known option key. If none is found, the whole string is treated as a plain username. Once one is found, every following segment must be a valid key-value pair — wrong order, duplicates and unknown keys are all rejected.
Invalid option syntax returns HTTP 400 invalid_proxy_parameters; missing or incorrect credentials return 407. SOCKS5 returns failure in the auth sub-negotiation.
Authentication and quota
The gateway exchanges the username and password with the control plane for an account snapshot, then checks account status, expiry, and remaining traffic.
Effective balance is min(user pool remaining, sub-account cap − sub-account used). When a sub-account has its own cap, having traffic left in the pool does not mean this sub-account can spend it.
Disabled or expired accounts return HTTP 403; exhausted traffic or account quota returns 402; account concurrency/rate limits return 429. An unavailable or timed-out authentication service returns 503; a destination connection timeout returns 504.
Route selection
Using your country, state, city and ASN plus the products the account is entitled to, the gateway filters the exit routes that can satisfy the request. With session present it first looks up the session binding and stays on the bound route if it hits.
If no route satisfies every condition: HTTP 503 service_unavailable, SOCKS5 reply 0x01.
Target policy check
The gateway checks whether the destination address and port are allowed. Private, loopback and link-local addresses are always refused. Hostnames are resolved at the gateway and pinned to the first resolved IP, so DNS cannot change after the check passes.
Failure here: HTTP 403. See Target restrictions.
Open the exit connection and relay
The gateway dials the selected exit and completes its handshake, then answers you with 200 Connection Established (HTTP) or reply 0x00 (SOCKS5). From there it is a plain bidirectional TCP relay.
Metering starts at this moment, not before.
Where metering begins
Only payload bytes successfully written to the peer socket are counted, in both directions. Concretely:
Counted:
- Everything inside the tunnel after CONNECT succeeds — TLS handshake records, HTTP headers, bodies
- The reconstructed request line and headers in ordinary HTTP forward mode
- Both upload and download
Not counted:
- The
CONNECTrequest line and headers you send to the gateway - The
200 Connection Establishedthe gateway sends back - SOCKS5 greeting, authentication, CONNECT request and reply
- The handshake between gateway and exit
- TCP/IP packet headers
So: handshakes are free, everything inside the tunnel is billed. Full accounting and multipliers are in Traffic accounting.
What a session binding actually binds
The sticky session key is accountID : productID : sessionValue, and it binds an exit route by default — not one specific IP.
That distinction matters in practice. The same session value keeps you on one route, which in the vast majority of cases means the same exit IP. But residential IPs come and go, and once that IP drops out of the route the gateway has no way to bring it back. Workloads that genuinely need one unchanging IP should use static residential or datacenter instead of leaning on dynamic residential stickiness.
What happens without a session
Without session no binding is created, and every new TCP connection goes through route selection independently.
Note that this is not the same as "a different IP per HTTP request": multiple requests inside one CONNECT tunnel or one keep-alive connection share the same tunnel and the same exit. To change IP, the client has to open a new connection. See the integration guides for how to force that in each language.