Proxy authentication decides who may send traffic through a proxy gateway. There are two common methods: username and password, where the client proves identity on every connection with a Proxy-Authorization header, and an IP allowlist, where the gateway accepts any connection from a registered source address. Username and password works from anywhere and ties usage to a credential; an allowlist needs no client support but ties usage to a network location. Most production setups use credentials by default and reserve allowlisting for tools that cannot send them.
Both methods are available on every ProxyForge line. This article explains how each works at the protocol level, where each one fits, and what each costs you in security terms.
How username and password proxy authentication works
HTTP defines a challenge-response exchange specifically for proxies, separate from the one used by origin servers. It is specified in RFC 9110:
- The client sends a request to the proxy without credentials.
- The proxy answers
407 Proxy Authentication Requiredwith aProxy-Authenticateheader naming the scheme it accepts, usuallyBasic. - The client repeats the request with a
Proxy-Authorizationheader carrying the credentials. - The proxy validates them and forwards the request, or opens a tunnel for HTTPS.
Most clients skip the first round trip: if the proxy URL contains a username and password, they send Proxy-Authorization preemptively. The header value for the Basic scheme, defined in RFC 7617, is the word Basic followed by username:password encoded in base64. Base64 is an encoding, not encryption. Anyone who can read the header can recover the password.
For HTTPS targets, the credentials travel on the CONNECT request that opens the tunnel. The target never sees them, but with a plain http:// proxy URL, that CONNECT request crosses the network between your client and the gateway unencrypted, before the tunnel's TLS begins. That is one reason to keep proxy credentials scoped and rotatable rather than treating them as low-value.
SOCKS5 has its own mechanism. The client and proxy negotiate an authentication method during the handshake, and username and password authentication is a separate sub-negotiation defined in RFC 1929. The same caveat applies: the credentials are sent in clear on the client-to-gateway hop.
How IP allowlisting works
An allowlist moves authentication from the request to the network layer. You register one or more public source addresses, and the gateway accepts connections that arrive from them without asking for credentials. No header is sent, no challenge is issued, and the client needs no proxy authentication support at all: it only needs to know the gateway host and port.
The important detail is which address the gateway sees. It is the public address at the end of your outbound path, after every layer of network address translation. For a laptop on a home network, that is the router's address. For a workload in a cloud VPC, it is the NAT gateway's address. For a corporate network, it is the firewall's egress address, which may be one of several. For Kubernetes, it is the node's address, a cloud NAT address, or an egress gateway's address, depending on how the cluster is configured.
The reliable way to find it is to ask from the place the traffic will originate:
curl -s https://api.ipify.org
Run that on the host, inside the pod, or from the function, not from your workstation. If it prints different addresses on different runs, you do not have a stable egress address, and an allowlist will fail intermittently.
When does each method fit?
Where an IP allowlist is the practical choice
Headless browsers that cannot send proxy credentials. Chrome's --proxy-server command-line flag accepts a host and port but not a username and password. Automation libraries work around this in different ways: Puppeteer answers the challenge through page.authenticate, and Playwright accepts a username and password in its proxy settings. Selenium with Chrome has no clean built-in route, and Chromium does not support username and password authentication for SOCKS5 proxies at all. In those cases, allowlisting the machine's egress address is the simplest correct setup. The per-tool details are in the Puppeteer proxy guide and the Selenium proxy guide.
Legacy tools and appliances. Some commercial crawlers, monitoring appliances and older HTTP libraries expose a proxy host and port field and nothing else.
Fixed infrastructure with a stable egress. A fleet behind a NAT gateway with a reserved address, or a Kubernetes cluster that routes proxy-bound traffic through a dedicated egress gateway, has one address to register and a network team that controls it.
Where username and password is the practical choice
Serverless and ephemeral compute. Functions, short-lived containers and hosted CI runners usually leave from shared, changing addresses. Unless you route them through a NAT with a reserved address, there is nothing stable to allowlist.
Developers and mixed locations. Engineers testing from home, from an office and from a VPN each have a different egress. Credentials follow the person or service, not the network.
Multiple teams on one account. An allowlisted address identifies a network, not a team. If two teams share a NAT gateway, the gateway cannot tell their traffic apart. Credentials per team can.
Anywhere you need attribution. With credentials, usage and spend are attached to a named credential. With an allowlist, they are attached to whoever controls an address.
Security trade-offs in production
Neither method is secure by default. Each fails in its own predictable ways.
Credentials leak into logs
The most common leak is the proxy URL itself. http://USERNAME:[email protected]:PORT is a convenient format, and a convenient thing to log. It ends up in debug output, exception messages that print the failing URL, crash reports, CI logs that echo environment variables, and process listings when passed as a command-line argument. Mitigations:
- Read the proxy URL from an environment variable or a secrets manager, never from source.
- Configure log scrubbing for the
Proxy-Authorizationheader and for any URL containing@. - Avoid passing credentials as command-line arguments on shared hosts, where other users can read the process table.
Special characters must be percent-encoded
A password that contains @, :, /, #, ? or % will break URL parsing if inserted raw, often in confusing ways: the client may treat part of the password as the host. Percent-encode the username and password before building the URL:
import os
from urllib.parse import quote
user = quote(os.environ["PROXY_USER"], safe="")
password = quote(os.environ["PROXY_PASS"], safe="")
host = os.environ["PROXY_HOST"]
proxy_url = f"http://{user}:{password}@{host}"
Clients that accept the username and password as separate fields, such as Playwright's proxy settings or curl's --proxy-user, take the raw values and do the encoding themselves. Do not encode twice.
An allowlisted address is a shared secret you do not fully control
An allowlist grants access to everyone behind that address. On a corporate network, that is every employee and every compromised device on the network. On a shared cloud NAT, it is every workload routed through it. On a hosted CI service, the address may be shared with other customers entirely, which is why CI runner ranges should never be allowlisted. Allowlist entries also outlive their purpose: an address released back to a cloud provider and reassigned to someone else still carries your access until you remove it.
Keep allowlists short, owned and reviewed. Every entry should map to a specific, reserved address with a named owner, and should be removed when the infrastructure behind it is retired.
Rotation and scoping
Credentials can be rotated; an address usually cannot. Plan rotation from the start:
- Issue separate credentials per team or per service, so that rotating one does not require every consumer to redeploy at once.
- Store them where your other service credentials live, with the same rotation schedule and the same access controls.
- Rotate immediately when a credential appears in a log, a ticket or a chat message, or when someone with access leaves.
On ProxyForge, teams work inside an organization whose members hold one of three roles: owners manage members, billing, API keys and settings; users buy and manage proxies; read-only members see usage and change nothing. That keeps the people who can change access separate from the people who run jobs, as described in managing proxy team access. A leaked proxy credential is still an incident: replace it, review recent usage, and prefer an IP allowlist wherever your egress address is stable. Security reviewers will ask about this; it appears in most proxy vendor security questionnaires.
IP allowlist vs username and password: comparison
| Consideration | Username and password | IP allowlist |
|---|---|---|
| Client support needed | Must send Proxy-Authorization or SOCKS5 credentials |
None beyond host and port |
| Works from changing egress IPs | Yes | No |
Works with Chrome's --proxy-server flag alone |
No | Yes |
| Attribution | Per credential, so per team or service | Per network address |
| Main leak path | Logs, URLs, environment dumps, process lists | Anyone else sharing the egress address |
| Rotation | Change the credential and redeploy consumers | Change the network, or remove and re-add the address |
| Failure mode when misconfigured | 407 on every request |
407 or refused connection, often intermittent behind NAT |
| Best fit | Serverless, CI, multi-team accounts, developer machines | Browsers without auth support, legacy tools, fixed egress fleets |
A common hybrid: use credentials everywhere by default, and add a small number of allowlisted, reserved addresses for the specific browser fleets that need them. Document which is which, because a request that fails with 407 looks the same under both methods.
Debugging a 407
A 407 Proxy Authentication Required means the gateway did not accept the connection as authenticated. Work through it in order:
- Confirm which method you intend to use for this client, and that the account is configured for it.
- For credentials, copy the connection string again from the dashboard's configuration panel and test it with
curl -x "$PROXY_URL"from the same host. Ifcurlsucceeds and your application fails, the application is building the URL or header differently, usually an encoding problem. - For an allowlist, run the egress check above from the exact host, pod or function that sends the traffic, and compare the result to the registered address.
- If the result varies between runs, your egress is not stable. Switch that workload to credentials or route it through a reserved NAT address.
The first-request walkthrough in how to set up a proxy and verify your first request includes a troubleshooting table that covers the other common failures.
How ProxyForge handles proxy authentication
Every ProxyForge line, residential, mobile, ISP and datacenter, supports username and password and IP allowlisting over HTTP, HTTPS and SOCKS5. Credentials are issued in the dashboard, and the dashboard's configuration panel generates the exact connection string for the country and session mode you choose, so encoding is handled for you.
If your security review needs more than this article covers, the data processing agreement is available to review before you sign, traffic metadata is retained for 30 days, and a named engineer can answer the questions a questionnaire leaves open.