[{"data":1,"prerenderedAt":19},["ShallowReactive",2],{"blog:post:en:proxy-basic-auth-vs-api-bearer-tokens":3},{"slug":4,"lang":5,"title":6,"summary":7,"date":8,"tags":9,"tag_slugs":14,"thumbnail_url":15,"translations":16,"body":17,"asset_base":18},"proxy-basic-auth-vs-api-bearer-tokens","en","Proxy Basic Auth vs API Bearer Tokens in Rotating Setups","Learn the difference between proxy connection credentials and session API authentication, with code examples for cURL, Python, and on-demand rotation.","2026-11-06",[10,11,12,13],"proxy","authentication","api","rotation",[10,11,12,13],"https://blog-api.ro-proxy.com/api/blog/posts/proxy-basic-auth-vs-api-bearer-tokens/thumbnail.svg?lang=en",[5],"## Why Rotating Proxies Use Two Authentication Layers\n\nA rotating proxy setup has two separate jobs: moving your traffic through an exit IP, and managing the session that assigns that IP. Because those jobs are handled by different systems, they require different authentication.\n\nConfusing the two layers is a common source of 401 and 407 errors. The proxy tunnel needs session credentials for every request. The control plane needs an API key only when you list or rotate sessions. This post explains each layer, why they are separate, and how to use them together with cURL, Python, and shell scripts.\n\n## Layer 1: Proxy Connection Credentials (Basic Auth)\n\n### How the credentials work\n\nEvery request that passes through the proxy must authenticate to the gateway. The standard way is to embed the session username and password in the proxy URL:\n\n```\nhttp://USERNAME:PASSWORD@GATEWAY_HOST:HTTP_PORT\n```\n\nThe same HTTP port is used for both HTTP and HTTPS targets. For HTTPS, the client sends a `CONNECT` request through the proxy, and the gateway tunnels the encrypted traffic to the destination. Because the proxy never sees the decrypted HTTPS payload, one port can serve both schemes.\n\nEach session has its own username and password. If you create multiple sessions, do not mix their credentials; a password from session A will not work with session B.\n\n### cURL examples\n\nYou can pass the credentials directly in the URL:\n\n```bash\ncurl -x http://USERNAME:PASSWORD@GATEWAY_HOST:HTTP_PORT \\\n  https://api.ipify.org?format=json\n```\n\nAlternatively, split the host and credentials:\n\n```bash\ncurl --proxy http://GATEWAY_HOST:HTTP_PORT \\\n  --proxy-user USERNAME:PASSWORD \\\n  https://api.ipify.org?format=json\n```\n\nBoth forms tell cURL to authenticate to the proxy before fetching the target. The `-v` flag is useful for debugging because it shows the proxy negotiation and any `407 Proxy Authentication Required` response.\n\n### Python example\n\nThe `requests` library accepts a `proxies` dictionary. Use the same URL for both `http` and `https` keys because the gateway port handles both:\n\n```python\nimport requests\n\nproxies = {\n    'http': 'http://USERNAME:PASSWORD@GATEWAY_HOST:HTTP_PORT',\n    'https': 'http://USERNAME:PASSWORD@GATEWAY_HOST:HTTP_PORT',\n}\n\nresponse = requests.get(\n    'https://api.ipify.org?format=json',\n    proxies=proxies,\n    timeout=30,\n)\nprint(response.json())\n```\n\nIf you are using RoProxy, configure your client with the username and password for the session you created. Each session has its own credentials, so do not reuse one session's password with another session's ID.\n\n### Environment variables\n\nMany command-line tools and language runtimes read `HTTP_PROXY` and `HTTPS_PROXY` automatically. This avoids hardcoding credentials in every script:\n\n```bash\nexport HTTP_PROXY='http://USERNAME:PASSWORD@GATEWAY_HOST:HTTP_PORT'\nexport HTTPS_PROXY='http://USERNAME:PASSWORD@GATEWAY_HOST:HTTP_PORT'\nexport NO_PROXY='localhost,127.0.0.1,.internal'\n```\n\nThe `NO_PROXY` list keeps local and internal traffic out of the tunnel, which prevents loops and unnecessary latency.\n\n## Layer 2: Session API Authentication (Bearer Token)\n\n### What the API key controls\n\nThe backend API is where you manage sessions, not where you send traffic. Authentication uses a bearer token in the request header:\n\n```\nAuthorization: Bearer API_KEY\n```\n\nThis header is never added to requests that go through the proxy to a target website. It is sent only to the API endpoints.\n\nList your sessions:\n\n```bash\ncurl -s -H 'Authorization: Bearer API_KEY' \\\n  https://backend-api.ro-proxy.com/api/session\n```\n\nRotate a session's IP immediately:\n\n```bash\ncurl -s -X POST -H 'Authorization: Bearer API_KEY' \\\n  https://backend-api.ro-proxy.com/api/session/SESSION_ID/rotate\n```\n\n### Why the layers are separate\n\nSeparating data-plane credentials from control-plane credentials follows a basic security principle: the token used to change your exit IP should not be transmitted to every website you visit. If your application logs outgoing HTTP headers, the API key stays out of those logs because it is never sent through the proxy tunnel.\n\n## Rotation Modes and What Actually Changes\n\nA session has a rotation mode that determines when its exit IP changes:\n\n- **Sticky:** Keeps the same IP until you rotate it manually or the IP fails. The session credentials stay the same.\n- **Timed:** Changes the IP after an interval you set. The session credentials stay the same.\n- **Per request:** Uses a new IP for every new connection. Available on the Business plan only. The session credentials stay the same.\n\nRotation changes the upstream IP mapped to your session. It does not change the username or password you use to authenticate to the gateway. That means your client configuration can remain static while the exit IP changes behind the scenes.\n\n## End-to-End Example: Check IP, Rotate, Verify\n\nHere is a shell sequence that lists sessions, checks the current exit IP, rotates, and checks again.\n\n1. List sessions and note the `SESSION_ID`:\n\n```bash\ncurl -s -H 'Authorization: Bearer API_KEY' \\\n  https://backend-api.ro-proxy.com/api/session\n```\n\n2. Check the exit IP through the proxy:\n\n```bash\ncurl -s -x http://USERNAME:PASSWORD@GATEWAY_HOST:HTTP_PORT \\\n  https://api.ipify.org?format=json\n```\n\n3. Rotate the session:\n\n```bash\ncurl -s -X POST -H 'Authorization: Bearer API_KEY' \\\n  https://backend-api.ro-proxy.com/api/session/SESSION_ID/rotate\n```\n\n4. Check the exit IP again:\n\n```bash\ncurl -s -x http://USERNAME:PASSWORD@GATEWAY_HOST:HTTP_PORT \\\n  https://api.ipify.org?format=json\n```\n\nThe `ip` field in the JSON response should change between step 2 and step 4. If it does not, the session may be in sticky mode and the previous IP may still be valid, or the rotate request may have returned an error.\n\n## Python Script: Rotate on Target-Side Errors\n\nFor long-running scripts, you can automate rotation when the target returns `403 Forbidden` or `429 Too Many Requests`. Do not rotate on `407 Proxy Authentication Required`; that means your proxy credentials are wrong, and rotating the IP will not fix authentication.\n\n```python\nimport requests\nimport time\n\nAPI_KEY = 'API_KEY'\nSESSION_ID = 'SESSION_ID'\nUSERNAME = 'USERNAME'\nPASSWORD = 'PASSWORD'\nGATEWAY_HOST = 'GATEWAY_HOST'\nHTTP_PORT = 'HTTP_PORT'\n\nproxy_url = 'http://USERNAME:PASSWORD@GATEWAY_HOST:HTTP_PORT'\nproxies = {'http': proxy_url, 'https': proxy_url}\n\napi_headers = {'Authorization': 'Bearer API_KEY'}\n\n\ndef rotate_session():\n    url = 'https://backend-api.ro-proxy.com/api/session/' + SESSION_ID + '/rotate'\n    requests.post(url, headers=api_headers, timeout=30)\n\n\ndef fetch(url):\n    for attempt in range(2):\n        try:\n            response = requests.get(url, proxies=proxies, timeout=30)\n            if response.status_code in (403, 429):\n                rotate_session()\n                time.sleep(2)\n                continue\n            return response\n        except requests.RequestException:\n            if attempt == 0:\n                rotate_session()\n                time.sleep(2)\n            else:\n                raise\n    return requests.get(url, proxies=proxies, timeout=30)\n\n\nprint(fetch('https://api.ipify.org?format=json').json())\n```\n\nThis script keeps the proxy URL constant. When the target blocks the current exit IP, the script calls the API to rotate and retries once.\n\n## Choosing a Rotation Mode\n\n- Use **sticky** for multi-step flows such as login sequences or checkout funnels. Changing IP mid-flow can invalidate server-side sessions or trigger security checks.\n- Use **timed** for batch jobs that run for minutes or hours. You get predictable IP changes without writing rotation logic.\n- Use **per request** for stateless API calls where each request should originate from a different address. This mode is available on the Business plan only.\n\n## SOCKS5 as an Alternative Tunnel\n\nPro and Business plans also provide a `SOCKS5_PORT`. Unlike the HTTP gateway, SOCKS5 forwards raw TCP and does not interpret HTTP. It is useful when your application speaks a non-HTTP protocol or when you want the client to handle the `CONNECT` step itself.\n\n```bash\ncurl --socks5-hostname USERNAME:PASSWORD@GATEWAY_HOST:SOCKS5_PORT \\\n  https://api.ipify.org?format=json\n```\n\nChoose the HTTP gateway for browsers and standard HTTP clients. Choose SOCKS5 when your tool explicitly supports SOCKS5 or when you need UDP forwarding.\n\n## Debugging Authentication Failures\n\n- `407 Proxy Authentication Required`: Verify `USERNAME`, `PASSWORD`, `GATEWAY_HOST`, and `HTTP_PORT`. Ensure the session is active and you are not mixing credentials from different sessions.\n- `401 Unauthorized` from the API: Verify `API_KEY` and that the header is exactly `Authorization: Bearer API_KEY`.\n- `403 Forbidden` from the API: The session ID may not exist, or your plan may not support the requested action.\n- Use `curl -v` to see request and response headers. It reveals whether the client is authenticating to the proxy or to the target.\n\nNever put the API key in the proxy URL, and never put the session password in the `Authorization` header.\n\n## Conclusion\n\nRotating proxies work best when you treat the data plane and control plane as separate concerns. Use session username and password for the proxy tunnel, and use `Authorization: Bearer API_KEY` only for session management. Keep your proxy URL stable across rotations, and choose sticky, timed, or per-request mode based on whether your traffic is stateful or stateless.\n\nRoProxy support is available on Telegram if you need help with session credentials or API keys.\n","https://blog-api.ro-proxy.com/api/blog/posts/proxy-basic-auth-vs-api-bearer-tokens/assets",1793951898464]