[{"data":1,"prerenderedAt":19},["ShallowReactive",2],{"blog:post:en:list-test-and-rotate-proxy-sessions":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},"list-test-and-rotate-proxy-sessions","en","List, Test, and Rotate Proxy Sessions Programmatically","Use the sessions API to inventory active proxy sessions, verify the exit IP, and rotate an individual session without restarting your scraper.","2026-10-31",[10,11,12,13],"proxy","api","python","session-management",[10,11,12,13],"https://blog-api.ro-proxy.com/api/blog/posts/list-test-and-rotate-proxy-sessions/thumbnail.svg?lang=en",[5],"Running multiple scraping jobs through rotating proxy sessions creates an operational question: which session is attached to which script, and what do you do when a session stops returning the expected IP? Rather than restarting your application or guessing in a dashboard, you can query the session list, test the current exit address, and rotate an individual session on demand.\n\nThis guide walks through a focused workflow: list active sessions, match one to a running job, verify its exit IP, and trigger an immediate rotation using only the service’s REST API and Python’s request libraries. It assumes you already have at least one active session with a username and password.\n\nYour account may use sticky, timed, or per-request rotation modes. Sticky sessions keep the same IP until you rotate them or the IP fails. Timed sessions change the IP after an interval you set. Per-request sessions, available on Business plans, assign a new IP for every new connection. Knowing which mode applies to your session helps you decide when a manual rotation is necessary.\n\n## List your active sessions\n\nStart by retrieving every session tied to your account. The API requires an API key passed as a bearer token in the Authorization header.\n\n```python\nimport os\nimport json\nimport requests\n\nAPI_KEY = os.getenv(\"API_KEY\")\nSESSIONS_URL = \"https://backend-api.ro-proxy.com/api/session\"\n\nheaders = {\n    \"Authorization\": f\"Bearer {API_KEY}\"\n}\n\nresponse = requests.get(SESSIONS_URL, headers=headers, timeout=30)\nresponse.raise_for_status()\n\nsessions = response.json()\nprint(f\"Found {len(sessions)} sessions\")\nfor session in sessions:\n    print(json.dumps(session, indent=2))\n```\n\nThe response is a list of session objects. At minimum, each object should include the session identifier and the username assigned to that session. Keep the SESSION_ID value for the steps below; you will use it to address a single session for rotation.\n\nIf the request returns 401 or 403, verify that your API key is correct and that it is being sent exactly as `Authorization: Bearer API_KEY`. A non-200 response means the session list is unavailable, so do not proceed to rotation until authentication is fixed.\n\n## Match a session to a running job\n\nWhen several scripts share the same account, it helps to store the SESSION_ID in an environment variable or a small config file so each process knows which session it owns. This prevents one script from accidentally rotating another script’s IP mid-job.\n\n```python\nSESSION_ID = os.getenv(\"SESSION_ID\")\nif not SESSION_ID:\n    raise RuntimeError(\"SESSION_ID is not set\")\n```\n\nYour application should load this value at startup and pass it to any proxy configuration helper. That way, logs and error messages can reference a concrete session instead of a generic “proxy.”\n\n## Configure your client with your session credentials\n\nEach session connects through a gateway host on an HTTP port. That same HTTP port is used for both HTTP and HTTPS traffic. On Pro and Business plans, a separate SOCKS5 port is also available, but this guide uses the HTTP gateway because it works for standard web traffic.\n\nConfigure your HTTP client with your RoProxy session credentials:\n\n```python\nUSERNAME = os.getenv(\"USERNAME\")\nPASSWORD = os.getenv(\"PASSWORD\")\nGATEWAY_HOST = os.getenv(\"GATEWAY_HOST\")\nHTTP_PORT = os.getenv(\"HTTP_PORT\")\n\nproxy_url = f\"http://{USERNAME}:{PASSWORD}@{GATEWAY_HOST}:{HTTP_PORT}\"\n\nproxies = {\n    \"http\": proxy_url,\n    \"https\": proxy_url,\n}\n```\n\nPass this dictionary to `requests.get()` or `requests.post()`. Because the gateway handles HTTPS, you do not need a separate `https://` proxy URL; the scheme in the proxy string remains `http://`.\n\n## Test the current exit IP\n\nBefore rotating, confirm what IP the session is currently using. A reliable public endpoint for this check is httpbin.org.\n\n```python\ncheck_url = \"https://httpbin.org/ip\"\n\nresponse = requests.get(check_url, proxies=proxies, timeout=30)\nresponse.raise_for_status()\n\norigin = response.json().get(\"origin\")\nprint(f\"Current exit IP: {origin}\")\n```\n\nRecord this IP in your logs or a temporary file. You will compare it to the result after rotation to verify that the change actually took effect.\n\n## Rotate a single session on demand\n\nWhen you need a new IP immediately—because the current one is blocked, returning errors, or simply exhausted for your task—call the rotate endpoint for that session only.\n\n```python\nROTATE_URL = f\"https://backend-api.ro-proxy.com/api/session/{SESSION_ID}/rotate\"\n\nrotate_response = requests.post(ROTATE_URL, headers=headers, timeout=30)\nrotate_response.raise_for_status()\n\nprint(f\"Rotation requested for session {SESSION_ID}\")\n```\n\nThe endpoint changes the session’s IP at once. It does not restart your Python process or interrupt existing TCP connections that are already open; it applies to new connections made after the call completes.\n\n## Verify the rotation worked\n\nImmediately after the rotate call, request the IP check endpoint again through the same proxy configuration.\n\n```python\nresponse = requests.get(check_url, proxies=proxies, timeout=30)\nresponse.raise_for_status()\n\nnew_origin = response.json().get(\"origin\")\nprint(f\"New exit IP: {new_origin}\")\n\nif new_origin == origin:\n    print(\"Warning: exit IP did not change. The session may still be rotating or the IP failed to assign.\")\nelse:\n    print(\"Rotation verified.\")\n```\n\nIf the IP does not change within a few seconds, check whether the session is in sticky mode. Sticky sessions keep the same IP until you rotate them or the IP fails, so a manual rotate call is exactly the right tool. Timed sessions change automatically after the interval you set, so manual rotation is less necessary unless you need an unscheduled change. Per-request sessions, available on Business plans, assign a new IP for every new connection and do not require manual rotation at all.\n\n## Build a small health-check loop\n\nFor a fleet of sessions, combine the list, test, and rotate steps into a maintenance script. This example tests each session and rotates any that return an unexpected origin or fail to connect.\n\n```python\nimport time\n\nEXPECTED_ORIGIN_PREFIX = \"203.0.113\"  # Example only; replace with your expected range\n\ndef test_session(session):\n    sid = session.get(\"id\")\n    user = session.get(\"username\")\n    # Rebuild proxy URL for this session\n    proxy_url = f\"http://{user}:{PASSWORD}@{GATEWAY_HOST}:{HTTP_PORT}\"\n    proxies = {\"http\": proxy_url, \"https\": proxy_url}\n    try:\n        r = requests.get(check_url, proxies=proxies, timeout=15)\n        r.raise_for_status()\n        ip = r.json().get(\"origin\", \"\")\n        return sid, ip, None\n    except Exception as exc:\n        return sid, None, exc\n\nfor session in sessions:\n    sid, ip, error = test_session(session)\n    if error:\n        print(f\"Session {sid} failed: {error}. Rotating...\")\n        requests.post(\n            f\"https://backend-api.ro-proxy.com/api/session/{sid}/rotate\",\n            headers=headers,\n            timeout=30,\n        )\n    elif ip and not ip.startswith(EXPECTED_ORIGIN_PREFIX):\n        print(f\"Session {sid} returned unexpected IP {ip}. Rotating...\")\n        requests.post(\n            f\"https://backend-api.ro-proxy.com/api/session/{sid}/rotate\",\n            headers=headers,\n            timeout=30,\n        )\n    else:\n        print(f\"Session {sid} is healthy with IP {ip}\")\n    time.sleep(1)\n```\n\nDo not run this loop too frequently. Rapid manual rotation can interfere with timed schedules and may consume session allowances faster than intended. Rotate only when a session is genuinely unhealthy or when your task requires a new IP on demand.\n\n## Error handling and retries\n\nNetwork requests to the API can fail for reasons unrelated to your proxy session. Wrap both the list and rotate calls in try/except blocks, and consider a short retry with backoff for 5xx responses. If the rotate endpoint returns 404, the SESSION_ID may be invalid or the session may have been deleted. If it returns 429, slow down your rotation requests.\n\nNever log your API_KEY, USERNAME, or PASSWORD in plain text. Load them from environment variables or a secrets manager, and exclude any file containing them from version control.\n\n## Conclusion\n\nKeeping track of individual proxy sessions turns rotation from a black box into a controllable operation. By listing sessions, testing exit IPs, and calling the rotate endpoint for a specific SESSION_ID, you can recover from a blocked address without restarting your scraper or affecting other jobs running under the same account.\n\nIf you do not have a session yet, RoProxy gives new accounts free sessions to try the service, and support is available on Telegram.\n","https://blog-api.ro-proxy.com/api/blog/posts/list-test-and-rotate-proxy-sessions/assets",1793430114983]