# Proxy authentication > Authenticate HTTP or SOCKS5 with a routing username and your key as the password. > > Web page: https://ports.io/docs/reference/authentication/ > Documentation index: https://ports.io/llms.txt Authenticate each new proxy connection with a routing username and the complete proxy key secret as the password. HTTP proxies carry these credentials in Basic authentication; SOCKS5 carries them in its username/password handshake. Both protocols use the same credentials and routing rules. ## Credentials at a glance | Field | Value | Purpose | | --- | --- | --- | | Proxy endpoint | Your assigned proxy URL | Connects your client to the proxy service | | Username | `v1_rotate`, or another valid routing username | Selects rotation, a session, and optional geographic filters | | Password | Your complete `rp1_...` secret | Authorizes proxy connections for its workspace | The example prefix `rp1_...` is a placeholder. Supply the complete secret, without extra whitespace or a newline. A key's display name, ID, or visible suffix cannot be used as its password. ## Make an authenticated request Configure your assigned endpoint and a secret in your environment, then let the client construct the protocol's authentication exchange: ```sh curl --proxy "$PORTS_PROXY_URL" \ --proxy-user "v1_rotate:$PORTS_PROXY_KEY" \ --connect-timeout 15 \ --max-time 30 \ https://example.com/ ``` `PORTS_PROXY_URL` and `PORTS_PROXY_KEY` are application variables used in this example. Their values must come from your service configuration and key creation flow. Include the assigned scheme, hostname, and port; do not infer a SOCKS port from an HTTPS proxy URL. For curl, use an assigned `http://` or `https://` proxy URL for HTTP proxying, or `socks5h://` for SOCKS5 with remote DNS. An HTTPS destination establishes the corresponding tunnel and then negotiates TLS with the destination. See [Protocols and limits](https://ports.io/docs/reference/protocols-and-limits.md) for transport details. ## HTTP wire format Clients send one `Proxy-Authorization` header on the initial proxy request: ```http CONNECT example.com:443 HTTP/1.1 Host: example.com:443 Proxy-Authorization: Basic ``` The Base64 input is the UTF-8 string `username:password`. Use the standard Basic authentication encoder in your HTTP library. Do not send the key in an origin `Authorization` header, a URL query parameter, or a custom bearer header. Basic authentication encoding does not encrypt the credentials. Use the proxy transport supplied for your environment and protect the key as a secret. ## SOCKS5 authentication and remote DNS Configure SOCKS5 username/password authentication ([RFC 1929](https://www.rfc-editor.org/rfc/rfc1929)) with the routing username and full key. Do not Base64-encode the password or send an HTTP `Proxy-Authorization` header inside the SOCKS handshake. The gateway does not accept anonymous authentication. With curl or Python Requests, set `PORTS_PROXY_URL` to the assigned SOCKS endpoint using `socks5h://`. This sends the destination hostname to the proxy for the exit to resolve. Their `socks5://` mode sends a locally resolved IP address, which is refused because destinations must be hostnames. The `h` selects remote DNS; it does not encrypt the proxy connection. The username and password are each limited to 255 UTF-8 bytes. Send the complete key. See the [curl](https://ports.io/docs/guides/curl.md), [Python](https://ports.io/docs/guides/python.md), or [JavaScript](https://ports.io/docs/guides/javascript.md) guide for client-specific configuration. ## Change routing without replacing the key The same key can authenticate different routing usernames: ```text v1_rotate v1_rotate_countries_US v1_sticky_session_checkout-42_countries_US v1_fixed_session_audit-42_regions_EU ``` The username never needs an account or workspace ID. The verified password identifies the workspace automatically. See [Username reference](https://ports.io/docs/reference/username-reference.md) for the complete grammar. ## Authentication failures HTTP authentication failures return `407` with `Proxy-Authenticate: Basic`. The error code distinguishes `invalid_credentials`, `key_expired`, `key_revoked`, and `account_disabled`. SOCKS5 authentication failures return an RFC 1929 failure status, without HTTP headers or a JSON error body. Invalid usernames, invalid keys, expired or revoked keys, and disabled workspaces use the same failure status. A client that does not offer username/password authentication receives a no-acceptable-methods reply before authentication starts. Check the whole username and password together: an unsupported username is also an authentication failure. Modified or wrong-environment secrets are rejected. If an unchanged key suddenly fails across otherwise valid requests, use the [troubleshooting guide](https://ports.io/docs/reference/troubleshooting.md) before creating replacement keys. Revocation and workspace status changes have a [propagation interval](https://ports.io/docs/reference/key-lifecycle.md#revoke-or-expire-a-key). ## Protect credentials - Store secrets in a secret manager or environment configuration. - Keep them out of source code, browser-delivered applications, request logs, screenshots, and support messages. - Use separate keys for applications that need independent revocation. - Replace a leaked or lost key using the [key lifecycle guide](https://ports.io/docs/reference/key-lifecycle.md). A proxy key grants proxy connection access. It is not a management API token. --- # Username reference > The complete grammar, its clauses, and the validation rules. > > Web page: https://ports.io/docs/reference/username-reference/ > Documentation index: https://ports.io/llms.txt The proxy username is a versioned routing instruction. It chooses how an exit is selected and optionally restricts the eligible geography. The proxy key secret belongs in the password field. Use the same username grammar for HTTP proxy Basic authentication and SOCKS5 username/password authentication. ## Grammar ```text v1_rotate[_regions_][_countries_][_exclude_] v1_sticky_session_[_regions_][_countries_][_exclude_] v1_fixed_session_[_regions_][_countries_][_exclude_] ``` Square brackets mark optional clauses. They are documentation notation and must not appear in your actual username. Replace angle-bracket placeholders with values. The version and strategy come first. Optional clauses may follow in any order, but each clause can appear only once. ## Strategies | Strategy | Required session clause | Behavior | | --- | --- | --- | | `v1_rotate` | None; a session clause is rejected | Select an eligible exit for each new connection | | `v1_sticky` | `_session_` | Reuse the session binding; allow failover when its exit is unreachable | | `v1_fixed` | `_session_` | Reuse the session binding; do not fail over an unreachable bound exit | Rotation does not guarantee a different exit or IP on every connection. Connection reuse also does not trigger another exit selection. See [Sessions and rotation](https://ports.io/docs/reference/sessions.md). ## Clauses | Clause | Format | Example | | --- | --- | --- | | `session` | ASCII letters, digits, dots, or hyphens; not empty | `_session_checkout-42` | | `regions` | Supported region codes separated by hyphens | `_regions_NA-EU` | | `countries` | ISO 3166-1 alpha-2 codes separated by commas | `_countries_US,GB` | | `country` | Alias for `countries` | `_country_US` | | `exclude` | ISO 3166-1 alpha-2 codes separated by commas | `_exclude_RU,BY` | `country` and `countries` refer to the same clause. Using both in one username is rejected. The parser accepts version, strategy, clause names, region codes, and country codes without regard to letter case. Session IDs preserve their spelling and case. Use consistent lowercase strategy names and uppercase geographic codes in application configuration. ## Supported regions | Code | Region | | --- | --- | | `NA` | North America | | `SA` | South America | | `AF` | Africa | | `AS` | Asia | | `EU` | Europe | Only these five region codes are accepted. Country-code validation does not imply that an exit is currently available in that country. See [Geographic targeting](https://ports.io/docs/reference/targeting.md). ## Examples ```text # Any eligible exit, selected for each new connection v1_rotate # US or United Kingdom v1_rotate_countries_US,GB # Europe, excluding Russia and Belarus v1_rotate_regions_EU_exclude_RU,BY # Reuse a session with US routing and permit exit failover v1_sticky_session_checkout-42_countries_US # Reuse a session in Europe without exit failover v1_fixed_session_audit-42_regions_EU ``` The comments above explain the examples; copy only the username line into your client. ## Validation rules - The complete username must be between 1 and 255 UTF-8 bytes. - The version must be `v1`; the previous unversioned grammar is rejected. - Session IDs use ASCII letters and digits; they cannot contain underscores, spaces, slashes, accented letters, or other punctuation beyond `.` and `-`. - Lists cannot contain empty or duplicate values. - Country codes must be recognized two-letter ISO country codes: use `GB`, not `UK`. - Region lists use `-`; country and exclusion lists use `,`. - Unknown clauses, including city, ASN, and duration clauses, are rejected. These invalid examples produce HTTP `407 invalid_credentials`, or a SOCKS5 username/password authentication failure. SOCKS5 does not return the HTTP JSON error code: ```text v1_rotate_session_demo v1_sticky v1_fixed_session_demo_1 v1_rotate_regions_EU,NA v1_rotate_countries_US,US v1_rotate_country_US_countries_GB v1_rotate_city_london ``` --- # Geographic targeting > Filter exits by country or by region. > > Web page: https://ports.io/docs/reference/targeting/ > Documentation index: https://ports.io/llms.txt Use region and country clauses in your proxy username to restrict the exits eligible for a new connection. Filters select from available exits; they do not reserve capacity or guarantee availability in a location. The same geographic clauses work with HTTP and SOCKS5 proxy authentication. They belong in the routing username, while the full proxy key is the password. ## Target a country Use a two-letter ISO country code: ```text v1_rotate_countries_US ``` To allow several countries, separate codes with commas: ```text v1_rotate_countries_US,GB ``` This permits an exit in either the United States or the United Kingdom. The singular spelling `country` is accepted as an alias for `countries`: ```text v1_rotate_country_US ``` Use `countries` consistently when generating usernames programmatically. ## Target a region Use `NA`, `SA`, `AF`, `AS`, or `EU`. Multiple region codes use hyphens: ```text v1_rotate_regions_NA-EU ``` This permits exits in North America or Europe. See the [region table](https://ports.io/docs/reference/username-reference.md#supported-regions) for names. Exits in Oceania, such as Australia and New Zealand, have no region code. Target them by country, with `AU` or `NZ`. ## Combine filters Selections within one list are combined with OR. Different filter clauses are combined with AND. Exclusions are applied to the resulting set. ```text v1_rotate_regions_NA_countries_US,MX_exclude_MX ``` The exit must match North America and must be in either the US or Mexico, then Mexico is removed. The resulting selection permits only matching US exits. | Username filters | Eligible geography | | --- | --- | | No geographic clauses | Any eligible exit | | `_countries_US,GB` | US or United Kingdom | | `_regions_NA-EU` | North America or Europe | | `_regions_EU_countries_DE,FR` | Europe and either Germany or France | | `_countries_US,GB_exclude_GB` | US only | | `_countries_US_exclude_US` | Empty selection | The last example is syntactically valid but cannot match an exit. Similarly, contradictory region and country requirements can produce an empty selection. ## Apply targeting to a session The same filter clauses work with sticky and fixed strategies: ```text v1_sticky_session_checkout-42_countries_US v1_fixed_session_audit-42_regions_EU_countries_DE,FR ``` Keep the strategy and geographic policy stable for an existing session ID. Create a new session ID when changing its policy. Reusing an active ID with different filters can produce a session policy conflict during connection setup. ## Handle unavailable locations When no eligible exit matches the request, HTTP proxying returns `502 no_exit_available`; SOCKS5 returns a general-failure CONNECT reply (`0x01`). A valid country code can still have no active exits. See [Troubleshooting](https://ports.io/docs/reference/troubleshooting.md) for protocol-specific errors. Review contradictory clauses first, then consider a broader selection appropriate to your application. Do not silently broaden geography when your application requires a specific location. The username grammar currently has no city, state, postal-code, ASN, or carrier selector. A region or country filter refers to the exit's location metadata, not the destination website's location. --- # Sessions and rotation > Rotate exits, or keep related connections on one. > > Web page: https://ports.io/docs/reference/sessions/ > Documentation index: https://ports.io/llms.txt Choose a routing strategy for each new proxy connection: rotate among eligible exits, reuse a sticky session with failover, or reuse a fixed session without failover. ## Choose a strategy | Goal | Username | Exit behavior | | --- | --- | --- | | Independent connections | `v1_rotate` | Select an eligible exit each time a connection is opened | | Prefer continuity and allow recovery | `v1_sticky_session_job-42` | Reuse the binding; permit rebinding if its exit is unreachable | | Fail instead of changing a bound exit | `v1_fixed_session_job-42` | Reuse the binding; do not fail over an unreachable bound exit | Geographic filters can be appended to each strategy. Use a new session ID if you change a session's strategy or filters. HTTP and SOCKS5 use the same routing usernames and workspace-scoped session bindings. Changing proxy protocol does not independently create a new binding when the workspace, session ID, and routing policy stay the same. ## Rotation happens at connection boundaries ```text v1_rotate_countries_US,GB ``` An exit is selected when a new proxy connection is dialed. Requests sent over an existing HTTP CONNECT or SOCKS5 tunnel continue using that tunnel's exit. An eligible exit may be selected again on a later connection. Rotation is not a promise of a unique IP, and it does not switch an established tunnel between exits. If your client library pools or reuses tunnels, one tunnel may carry several destination requests. Close or replace the connection when you need another selection. ## Sticky sessions ```text v1_sticky_session_checkout-42_countries_US ``` The first connection establishes a session binding. Later connections using the same workspace, session ID, strategy, and geographic policy reuse that binding while it remains active. If the bound exit cannot be reached during connection setup, sticky routing can attempt to bind another eligible exit. The alternative must satisfy the same policy. A target website refusing a connection does not itself cause the session to rotate to another exit. Failover applies when establishing a connection. An already established tunnel is not transparently moved or replayed after a failure. ## Fixed sessions ```text v1_fixed_session_audit-42_regions_EU ``` Fixed routing refuses exit failover for an active binding. If its bound exit cannot be reached, the connection fails. If the bound exit leaves the network, a still-active fixed binding cannot rebind: later connection setup with that ID fails. Start a new session ID to request another exit. HTTP and SOCKS5 report setup failures differently; see [Troubleshooting](https://ports.io/docs/reference/troubleshooting.md). Fixed describes the binding's failover policy. It is not a dedicated-IP reservation or a permanent IP guarantee. Exit network addresses can change. ## Session identity and policy Session IDs are scoped to the workspace authenticated by the key. Different keys from the same workspace can therefore use the same session ID and binding. Different workspaces have separate session namespaces. For independent workers, assign independent IDs: ```text v1_sticky_session_worker-01_countries_US v1_sticky_session_worker-02_countries_US ``` Keep the exact policy stable for each ID, including list ordering. An active binding with a different strategy or policy can fail during connection setup. To request another policy or start a separate binding, choose a new session ID: ```text # Original policy v1_sticky_session_job-42-us_countries_US # New policy, with a new ID v1_sticky_session_job-42-gb_countries_GB ``` ## Binding lifetime Session bindings last a limited time set by the service. The username has no TTL or duration parameter, and sending traffic through a session does not guarantee that its binding stays. Do not treat a session ID as an indefinite IP reservation or rely on an open tunnel to preserve a binding for later connections. Plan for a binding to end at any time. After it expires, a new connection may acquire another eligible exit even when it uses the same ID. Existing tunnel lifetime and session binding lifetime are separate concerns; see [Protocols and limits](https://ports.io/docs/reference/protocols-and-limits.md). --- # Manage proxy keys > Create, rename, replace, and revoke keys. > > Web page: https://ports.io/docs/reference/key-lifecycle/ > Documentation index: https://ports.io/llms.txt Create a named proxy key for an application, copy its secret once, and use it as the proxy password. Key replacement is a create, update, and revoke workflow. ## Create a key 1. Sign in to the console and select the workspace that should own the traffic. 2. Open **API keys** and create a named key using an owner or admin account. 3. Choose when it expires: in 30 days, 90 days (the default), 1 year, or never. 4. Copy the complete secret from the creation response and store it in your application's secret configuration. The current key management service requires owner or admin access for key listing and changes. Workspace selection must match the authenticated management session. Choose a name that identifies the application or environment. Names are trimmed, limited to 80 characters, and cannot contain control characters. ## One-time secret display The full password is returned only when the key is created. Later key listings contain metadata and a suffix, not the secret. Treat the suffix as an identifier for troubleshooting, never as a usable password. If you lose the secret or the creation response, create a replacement and revoke the inaccessible key. The existing secret cannot be recovered from the console's key metadata. ## Use and rename a key The key secret is the password in [HTTP proxy Basic authentication or SOCKS5 username/password authentication](https://ports.io/docs/reference/authentication.md). Routing strategy and targeting belong in the username and can be changed without issuing another key. Renaming changes the display name only. It does not replace the secret, alter its expiration, or rotate an exit. A revoked key cannot be renamed. Use separate keys when applications need independent access removal. ## Replace a key For routine replacement: 1. Create a new key with the desired name and expiration. 2. Store it in your application's secret configuration. 3. Validate that the application can authenticate using the new key. 4. Update all application instances and scheduled jobs that use the old secret. 5. Revoke the old key after the transition is complete. If a key has leaked, revoke it promptly and deploy a replacement. Revocation blocks new connections after its policy update reaches the proxy servers. It does not automatically close existing tunnels; see the propagation and tunnel behavior below. Replacement does not require changing the routing username. Session bindings are scoped to the workspace rather than a particular key; using another key in the same workspace does not independently create a new session binding. ## Revoke or expire a key Revocation is permanent. It preserves the key's ID, creator, timestamps, and associated usage history. Revoked keys cannot be re-enabled, and their history remains visible in the key list. Each proxy server reloads revoked keys and disabled-workspace policy every 30 seconds. These changes normally reach new connections within about 30 seconds; a failed reload can delay propagation. Revocation is not an instantaneous distributed operation. An expired key is rejected during new connection setup. Already established HTTP CONNECT and SOCKS5 tunnels do not recheck key validity and are not automatically closed by expiration, revocation, or a disabled workspace. They continue until a client or origin disconnects, a network failure occurs, or the 10-minute inactivity or 2-hour lifetime limit is reached. Close existing application connections you control when they must stop immediately. A key with no expiration still remains subject to revocation and workspace authorization policy for new connections. These rules apply to both HTTP and SOCKS5 authentication. ## Key issuance capacity The current service limits each workspace to 1,024 total issued keys, including retained expired and revoked keys. Revoking a key does not restore an issuance slot. Prefer stable application keys with deliberate replacement intervals over creating a key per request or per session. If the console says the workspace has reached its key issuance limit, contact support about more capacity. If it says key issuance is temporarily at capacity, try again later. In both cases existing keys keep working and can still be revoked. ## Management authentication Proxy secrets grant `proxy:connect`. Key-management requests use an authenticated console session, workspace authorization, and origin checks. The proxy password is not a bearer token for key-management endpoints. See [Authentication](https://ports.io/docs/reference/authentication.md) for the proxy connection credential format. --- # Protocols and limits > HTTP and SOCKS5 support, remote DNS, size limits, and deadlines. > > Web page: https://ports.io/docs/reference/protocols-and-limits/ > Documentation index: https://ports.io/llms.txt The proxy supports HTTP forward requests, HTTP CONNECT tunnels, and authenticated SOCKS5 CONNECT tunnels over TCP. Destination hostnames are resolved by the selected exit. Connection and capacity settings depend on the environment serving your assigned endpoint. ## Supported proxy operations | Operation | Behavior | | --- | --- | | HTTP forward proxy | Send an absolute-form URL such as `http://example.com/path` | | HTTP CONNECT | Open a bidirectional TCP tunnel to a `host:port` destination | | SOCKS5 CONNECT | Open a TCP tunnel using username/password authentication and a destination hostname | | HTTPS destination | Establish an HTTP or SOCKS5 tunnel, then negotiate TLS with the destination | | SOCKS4, SOCKS5 BIND | Unsupported | | UDP, SOCKS5 UDP ASSOCIATE | Unsupported | ## Proxy transport and destination TLS Configure the client with the endpoint assigned for its proxy transport, including the port: | Proxy URL format | Client behavior | | --- | --- | | `http://HOST:PORT` | HTTP proxy connection over plaintext TCP | | `https://HOST:PORT` | HTTP proxy connection protected by TLS | | `socks5h://HOST:PORT` | SOCKS5 connection over plaintext TCP, with destination DNS delegated to the proxy | These are URL formats, not usable endpoints. Use your assigned hostname and port. The SOCKS endpoint can use a different port from the HTTPS proxy endpoint; changing only an `https://` URL's scheme does not configure the correct SOCKS transport. `socks5h` is the remote-DNS setting used by curl and Python Requests. Other libraries may provide a separate setting or an agent that always sends hostnames. SOCKS5 over TLS requires explicit client support and the assigned TLS endpoint; `socks5h://` alone does not enable it. See the [JavaScript guide](https://ports.io/docs/guides/javascript.md) for the agent configuration used there. An HTTPS destination URL protects traffic between the application and destination after the tunnel opens. It does not by itself protect the client-to-proxy authentication exchange. Keep certificate verification enabled for every TLS connection. The initial HTTP proxy request is HTTP/1.0 or HTTP/1.1. An established HTTP or SOCKS5 tunnel carries the destination protocol, including a client's TLS-negotiated HTTP version. ## HTTP forward requests ```http GET http://example.com/path HTTP/1.1 Host: example.com Proxy-Authorization: Basic ``` The gateway forwards one complete HTTP request per forward-proxy connection and closes the connection after its response. HTTP pipelining and subsequent requests on that same connection are not forwarded. Because each forward request opens its own connection, `v1_rotate` selects an exit for each one. Request bodies require valid `Content-Length` or HTTP/1.1 `Transfer-Encoding: chunked` framing. Duplicate framing headers, simultaneous content length and transfer encoding, and unsupported transfer encodings are rejected. `Expect: 100-continue` is supported. Proxy credentials are removed from the forwarded request head, and so are `Upgrade` headers. CONNECT is required when your application needs a persistent bidirectional tunnel rather than a single HTTP exchange, including WebSocket connections. ## CONNECT tunnels ```http CONNECT example.com:443 HTTP/1.1 Host: example.com:443 Proxy-Authorization: Basic ``` On successful setup, the proxy responds with `200 Connection Established`. Subsequent bytes are passed through the selected exit. Multiple destination requests inside that tunnel use the same exit. Tunnels can end because of origin or client disconnects, network failure, or transfer deadlines. Applications should handle disconnects without assuming an established request was replayed. ## SOCKS5 tunnels Use SOCKS5 username/password authentication: the username is a routing policy such as `v1_rotate`, and the password is the complete proxy key. The gateway requires this method; anonymous SOCKS5 and SOCKS4 are refused. HTTP and SOCKS5 use the same routing usernames, key verification, session bindings, and usage measurements. The CONNECT request must carry a hostname. With curl or Requests, configure `socks5h://` so the client passes that hostname to the proxy. Their `socks5://` mode resolves the destination locally and sends an IP address, which the gateway rejects. An IP-literal destination is also rejected when remote DNS is enabled. A successful SOCKS5 CONNECT reply opens a bidirectional TCP tunnel. Subsequent bytes pass through the selected exit, and requests that reuse the tunnel use the same exit. BIND and UDP ASSOCIATE are refused with command-not-supported replies. See [Troubleshooting](https://ports.io/docs/reference/troubleshooting.md#socks5-failures) for the handshake and reply codes. ## Format limits | Input | Current limit | | --- | --- | | Proxy username | 1 to 255 UTF-8 bytes | | Proxy password | 1 to 255 UTF-8 bytes | | Destination hostname | At most 253 ASCII bytes after IDN conversion; each label at most 63 bytes | | Initial HTTP request head | 64 KiB | | Headers in the initial request | At most 64 | | Key display name | 1 to 80 characters after trimming; no control characters | | Key expiration | 30 days, 90 days, 1 year, or no expiration | The full key secret is required. Truncating it to fit another integration's field will make authentication fail. ## Destinations Supply a destination hostname, not an IPv4 or IPv6 literal, in HTTP forward URLs, HTTP CONNECT authorities, and SOCKS5 CONNECT requests. This restriction concerns the destination, not the assigned proxy's own address. Exits resolve the hostname and apply policy to the resulting socket addresses before connecting. By default, loopback, private networks, link-local addresses, shared address space, multicast, reserved and documentation ranges, and certain IPv6 special-purpose ranges are blocked. Port zero is rejected. The service can apply additional destination restrictions. A hostname resolving only to disallowed addresses will fail; an application cannot bypass this policy with a username clause. ## Connection and capacity settings The gateway enforces limits on concurrent connections, connections per source IP, and new connection rate. Clients sharing a NAT can share source-IP limits. Capacity refusals can close a connection before its proxy handshake completes. HTTP CONNECT and SOCKS5 tunnels are subject to a 10-minute inactivity deadline and a 2-hour lifetime deadline. An HTTP forward request has 10 minutes to send its request body, and the whole exchange ends after 2 hours. Your assigned environment's surrounding infrastructure can impose shorter deadlines. The initial HTTP request head or the full SOCKS5 negotiation, authentication, and CONNECT request must finish within the environment's setup deadline. All SOCKS5 handshake steps share that deadline. Key validity is checked during connection setup. Revocation, expiration, or disabling a workspace blocks new connections; an already established tunnel is not automatically closed by those changes. See [key lifecycle](https://ports.io/docs/reference/key-lifecycle.md#revoke-or-expire-a-key) for propagation behavior. Confirm the effective limits for your assigned environment before sizing production workloads. This documentation does not define a plan quota or a guaranteed concurrency level. Use bounded concurrency, deliberate connection reuse, and limited retries with backoff. See [Troubleshooting](https://ports.io/docs/reference/troubleshooting.md) for failure behavior. --- # Errors and troubleshooting > Diagnose HTTP proxy errors and SOCKS5 handshake or tunnel failures. > > Web page: https://ports.io/docs/reference/troubleshooting/ > Documentation index: https://ports.io/llms.txt Identify the proxy protocol and the stage that failed. HTTP proxy setup can return an HTTP status, JSON error code, and `Proxy-Status` header. SOCKS5 setup returns handshake statuses and binary reply codes. A destination response received after successful tunnel setup belongs to the destination. ## HTTP proxy error reference | Status | Error code | Meaning | First action | | --- | --- | --- | --- | | `400` | `invalid_request` | Malformed proxy request or invalid hostname/port | Correct the request format | | `400` | `ip_target_unsupported` | The destination is an IP address | Use a destination hostname | | `501` | `method_not_supported` | The HTTP proxy request is neither CONNECT nor absolute-form forwarding | Use the HTTP client's proxy settings | | `407` | `invalid_credentials` | Proxy credentials or routing username are invalid | Check the username and complete key secret | | `407` | `key_expired` | The key has expired | Create a replacement key | | `407` | `key_revoked` | The key has been revoked | Use a valid replacement key | | `407` | `account_disabled` | The workspace is disabled | Check its status in the console and contact support | | `502` | `no_exit_available` | No eligible exit matches the requested route | Check filters and location availability | | `503` | `routing_unavailable` | Route selection could not complete | Retry a safe request later with bounded backoff | | `502` | `exit_unreachable` | The selected exit could not be reached | Check session policy; retry a safe request with backoff | | `504` | `exit_timeout` | The selected exit did not respond in time | Reduce immediate retries and check destination access | | `502` | `target_dns_failed` | The exit could not resolve the hostname to permitted addresses | Check the hostname and destination policy | | `502` | `target_unreachable` | The exit could not connect to the destination | Check the destination hostname, port, and availability | | `502` | `target_closed` | An HTTP forward destination closed without a response | Retry only if the request can safely be repeated | Admission limits can also close a connection before setup without a structured HTTP response. A connection can close before parsing or when its initial request misses the setup deadline. ## HTTP error shape Structured setup failures use this shape: ```http HTTP/1.1 502 Bad Gateway Proxy-Status: ports.io; error=destination_unavailable; details="target_unreachable" Content-Type: application/json {"error":{"code":"target_unreachable","message":"the exit could not connect to the target"}} ``` Use `error.code` for machine classification. The `Proxy-Status` header's `details` field carries the same code, which can help when an HTTP library exposes a failed CONNECT response's headers but not its body. Do not depend on `error.message` as a stable programmatic identifier. A `407` also includes `Proxy-Authenticate: Basic`. ## SOCKS5 failures SOCKS5 does not return HTTP `407` or a JSON error body during setup. First determine whether method negotiation, username/password authentication, or the CONNECT request failed. | Stage | Value | Meaning | First action | | --- | --- | --- | --- | | Method negotiation | `0xff` | No acceptable authentication method | Enable SOCKS5 username/password authentication | | Username/password authentication | `0x01` | Authentication failed | Check routing username, full key, expiration, revocation, and workspace status | After successful authentication, these CONNECT reply codes can occur: | Reply code | Meaning in this gateway | First action | | --- | --- | --- | | `0x01` | General failure, including an invalid request, unavailable routing, or an unreachable exit | Check request format and route; retry transient failures with backoff | | `0x02` | Destination IP address rejected by policy | Enable remote DNS and use a destination hostname | | `0x04` | Destination DNS or connection failure | Check hostname, port, reachability, and destination restrictions | | `0x06` | Selected exit timed out | Retry a safe request later with backoff | | `0x07` | Command not supported | Use CONNECT; BIND and UDP ASSOCIATE are unsupported | | `0x08` | Unknown address type | Use a SOCKS5 client that sends a domain-name address | SOCKS replies group several internal failure causes. Authentication failure does not distinguish an invalid key from an expired or revoked one. Record the client error and the stage instead of expecting the HTTP error catalog's JSON codes. For curl or Python Requests, use `socks5h://` to send the destination hostname. Their `socks5://` mode resolves locally and sends an IP address, which receives `0x02`. A destination URL containing an IP literal also fails with remote DNS enabled. See [Protocols and limits](https://ports.io/docs/reference/protocols-and-limits.md#destinations). ## Resolve authentication failures 1. Use a valid routing username such as `v1_rotate`; account IDs and key display names do not belong in it. 2. Send the complete proxy key secret as the password. Remove copied whitespace and newlines. 3. Configure proxy Basic authentication for HTTP, or username/password authentication for SOCKS5. Do not use destination authentication or a bearer token. 4. Check whether the key has expired or been revoked, whether its workspace is enabled, and whether it belongs to the assigned environment. If an unchanged key fails across valid usernames, investigate the workspace and service status before creating more keys. Repeatedly creating keys will not resolve a service outage. ## Check destination and session failures For `no_exit_available`, look for filters that contradict each other or remove every permitted country. A recognized country code can still have no active exit. For destination DNS or connection failures, check that the hostname and port are correct and reachable from a public network. Private and special-purpose destinations are blocked by default. A destination may also refuse connections or deny requests based on its own policy. For a session, preserve the strategy and filter policy associated with the ID. Choose a new ID when changing either. Fixed sessions do not fail over an unreachable bound exit. See [Sessions and rotation](https://ports.io/docs/reference/sessions.md). ## Handle admission failures and connection drops Reduce parallel connections and avoid a burst of immediate retries. Proxy setup can be rejected by source-IP, concurrency, or connection-rate limits, unavailable routing, or destination policy. After HTTP `200 Connection Established` or a successful SOCKS5 CONNECT reply, the tunnel can still close because of a network failure, an origin or client disconnect, or the idle/lifetime deadline. Established traffic is not replayed by the proxy. Retry only when your application can safely repeat the operation; use capped exponential backoff and jitter for transient failures. ## Reproduce with a minimal client Use your assigned endpoint, an existing valid key, a plain routing username, and a destination hostname: ```sh curl --proxy "$PORTS_PROXY_URL" \ --proxy-user "v1_rotate:$PORTS_PROXY_KEY" \ --connect-timeout 15 \ --max-time 30 \ https://example.com/ ``` For SOCKS5, set `PORTS_PROXY_URL` to the assigned `socks5h://` endpoint with its port. For HTTP proxying, use the assigned `http://` or `https://` endpoint. A standard `socks5h://` connection cannot be sent directly to a TLS-only proxy port. Keep verbose traces private: they can include proxy or destination credentials. Remove credentials before sharing any diagnostic output. ## Information to include in a support report - Timestamp and timezone. - Proxy protocol, endpoint, and client/library version. - Routing username, destination hostname and port, and concurrency level. - Failure stage: negotiation, authentication, tunnel setup, or destination response. - HTTP proxy status/error code, or SOCKS handshake status/reply code when available. - Key ID or visible suffix, without the full secret. - Whether a minimal request reproduces the problem and whether other destinations work. The customer-facing error response currently has no documented request-ID field. Record your own request correlation ID when troubleshooting application batches.