Transfer diagnostics runbook

cURL Proxy Setup and 407 Troubleshooting

Configure an authenticated HTTP or SOCKS5 proxy in cURL, keep credentials out of URLs, prove which hop failed, and diagnose 407, DNS, TLS and timeout errors with copy-ready commands.

cURL

Command-line client

T-06
T-06 / Transfer diagnosticsSeparate the proxy hop from the destination hopserver-rendered route map

cURL process

flags + protected credentials

Proxy hop

TCP -> auth -> CONNECT

Destination hop

TLS -> HTTP status -> body

Record proxy connection, authentication, tunnel and destination evidence separately before changing routing or retry policy.

By Robert SmithReviewed by Michael Weber16 min runbook

Operating principle

Record proxy connection, authentication, tunnel and destination evidence separately before changing routing or retry policy.

Start With One Known-Good cURL Proxy Command

The dependable baseline is to keep the proxy address, proxy credentials and destination URL in separate arguments. For an HTTPS destination through Databay's HTTP gateway, cURL opens a TCP connection to the gateway, authenticates that proxy hop, asks it to create a CONNECT tunnel to the destination, and only then performs destination TLS inside the tunnel.

curl --disable \
  --proxy http://gw.databay.co:8888 \
  --proxy-user "$DATABAY_PROXY_USER:$DATABAY_PROXY_PASS" \
  --proxy-basic \
  --connect-timeout 5 \
  --max-time 20 \
  --fail-with-body \
  https://api.ipify.org?format=json

--disable prevents a default .curlrc from silently changing the test. --proxy describes the client-to-proxy protocol; the https:// destination still receives end-to-end TLS. --proxy-user is proxy authentication and is separate from --user, which authenticates to the destination. On Windows PowerShell, call curl.exe explicitly if curl resolves to another command.

The response from an IP endpoint is an observed exit for that request, not proof of anonymity, safety or future routing. Run the first check against a harmless endpoint you control when possible, and never paste production credentials into a shared terminal, ticket or screenshot.

What We Captured on the Wire

We tested the commands on 2026-07-27 with curl 8.21.0 on Windows using isolated listeners bound to 127.0.0.1. The destination name was the reserved example.test; the harness did not contact that domain or a public proxy. It redacted credential values before recording observations.

ModeFirst meaningful proxy messageObserved result
HTTP destination via HTTP proxyGET http://example.test/basic HTTP/1.1The proxy received an absolute-form URL and a redacted Basic Proxy-Authorization field.
HTTPS destination via HTTP proxyCONNECT example.test:443 HTTP/1.1The proxy received the destination authority and proxy credentials; destination TLS would begin only after a 2xx tunnel response.
No credentials plus --fail-with-body407 Proxy Authentication RequiredcURL exited 22 and retained the local lab's explanatory response body.
--proxy-anyauthUnauthenticated request, then authenticated retryThe lab recorded two requests, confirming the extra challenge round trip.
socks5h:// with username/passwordSOCKS5 method negotiation, auth sub-negotiation, then CONNECTThe request used address type 3 and carried example.test, so the proxy was asked to resolve the destination name.

This separation is the core diagnostic model: a TCP connection can reach the proxy while proxy authentication fails; authentication can succeed while CONNECT is denied; CONNECT can succeed while destination TLS fails; and TLS can succeed while the destination returns an HTTP error. Treating every failure as a bad proxy hides the layer that produced the evidence.

Keep Proxy Credentials Out of the Proxy URL

Embedding user:password@ in a proxy URL is convenient but fragile. Reserved characters require URL encoding, the entire value is easy to copy into logs, and a URL often travels through more tooling than a dedicated credential field. cURL's own manual also warns that a --proxy-user user:password argument can briefly be visible to other local users through process inspection even on systems where cURL later hides it.

For an interactive one-off test, injected environment variables are clearer than literals, but they are not a universal secret store. For automation, fetch the values from the platform's secret manager and stream a cURL configuration over standard input so the expanded credential is not part of cURL's argument vector:

{
  printf 'proxy = "%s"\n' 'http://gw.databay.co:8888'
  printf 'proxy-user = "%s:%s"\n' "$DATABAY_PROXY_USER" "$DATABAY_PROXY_PASS"
  printf '%s\n' 'proxy-basic' 'connect-timeout = 5' 'max-time = 20'
  printf 'url = "%s"\n' 'https://api.ipify.org?format=json'
} | curl --disable --config -

The localhost harness verified that --config - authenticated successfully while the cURL argument vector contained no password. Standard input still contains the credential in memory, so restrict access to the job and avoid shell tracing such as set -x. Do not save a credential-bearing .curlrc in a repository or reusable image. If a protected config file is operationally necessary, lock down its permissions, exclude it from backups and source control as appropriate, and rotate the credential after unintended exposure.

Choose HTTP, HTTPS, SOCKS5 or SOCKS5h Deliberately

There are two schemes in a proxied cURL command: the destination scheme and the proxy scheme. They answer different questions. An https:// destination through an http:// proxy is normal: HTTP describes the proxy control connection, while cURL tunnels destination TLS with CONNECT. An https:// proxy additionally applies TLS to the client-to-proxy hop and needs a cURL build with HTTPS-proxy support.

# HTTPS destination through an HTTP proxy
curl --proxy http://gw.databay.co:8888 https://service.example/

# Destination name resolved by the SOCKS5 proxy
curl --proxy socks5h://gw.databay.co:8888 https://service.example/

# Destination name resolved locally, then the IP is sent to SOCKS5
curl --proxy socks5://gw.databay.co:8888 https://service.example/

The final h in socks5h:// changes who resolves the destination hostname. Our capture received SOCKS5 address type 3 with the literal reserved domain under socks5h://. The separate protocol lab for HTTP versus SOCKS5 explains why that DNS choice is client-specific and why SOCKS5 alone does not add encryption, anonymity or UDP support to an application.

Use the protocol the actual client and network support. Do not switch protocols or DNS modes to work around a source block, authentication boundary or access policy.

Environment Variables and the NO_PROXY Trap

cURL can discover proxies from the environment. This is useful for a controlled worker image, but inherited settings are also a frequent reason a test unexpectedly bypasses or uses the wrong gateway.

VariableMeaning in cURLDiagnostic caution
http_proxyProxy for HTTP destination URLsOn case-sensitive platforms cURL accepts this name only in lowercase as a CGI security precaution.
HTTPS_PROXYProxy for HTTPS destination URLsThe name describes the destination scheme; its value can still begin with http://.
ALL_PROXYFallback when no scheme-specific variable existsA forgotten inherited value can affect several protocols.
NO_PROXYComma-separated hosts, domains or eligible CIDR ranges that bypass the proxy* bypasses the proxy for every destination. A matching entry can make a valid proxy appear unused.

Windows environment names are case-insensitive, so the lowercase-only distinction cannot be represented in the same way there. When proving an explicit --proxy setup, add --noproxy "" to neutralize an inherited bypass list. When proving environment behavior, print only variable names and routing decisions, never a credential-bearing value. cURL 8.7.0 and later can report proxy_used=1 through --write-out, which is more reliable than guessing from response time.

Diagnose 407 Without Confusing It With 401 or 403

A 407 is a proxy authentication challenge. RFC 9110 requires a proxy-generated 407 to include Proxy-Authenticate; a client responds with Proxy-Authorization. That is a different exchange from a destination's 401 and a different decision from a destination's 403.

  1. Confirm the response belongs to the proxy. Run one approved URL with --verbose locally and find the connection target plus the 407 and Proxy-Authenticate lines. Do not publish the full trace.
  2. Separate the credential fields. Use --proxy-user for the gateway. --user does not answer a proxy challenge.
  3. Check the authentication scheme. Basic is cURL's default proxy method. Use --proxy-anyauth only when the proxy advertises another supported method and an extra challenge request is acceptable.
  4. Validate the account grammar. Recheck the base username, password, pool and documented country or session flags. Do not assume a destination response proves the gateway rejected them.
  5. Test one request without concurrency. A minimal request removes retry loops, redirects and application headers from the diagnosis.

Our lab recorded two proxy requests for --proxy-anyauth: the first had no proxy credential and received the challenge; the second carried redacted Basic authentication. That extra round trip is expected. With no credential and --fail-with-body, the HTTP proxy lab produced exit code 22 plus The requested URL returned error: 407. HTTPS tunnel failures can surface differently by build and proxy behavior, so preserve both cURL's numeric exit code and the visible proxy response instead of hard-coding one universal 407 exit code.

Produce Evidence a CI Job Can Parse

Human-readable verbose output is useful at the terminal but noisy in automation. Use a small --write-out record and keep the response body separate:

curl --disable --silent --show-error --fail-with-body \
  --proxy http://gw.databay.co:8888 \
  --proxy-user "$DATABAY_PROXY_USER:$DATABAY_PROXY_PASS" \
  --connect-timeout 5 --max-time 20 \
  --output response.json \
  --write-out 'status=%{response_code} proxy=%{proxy_used} peer=%{remote_ip} connect=%{time_connect} tls=%{time_appconnect} total=%{time_total}\n' \
  https://api.ipify.org?format=json

In our HTTP lab, the record was status=200, proxy=1, and peer=127.0.0.1. The important interpretation is that remote_ip was the connected proxy socket, not the eventual exit IP. The controlled destination response is where an application can observe the exit address. time_connect covers the connection phase, time_appconnect records completion of destination TLS where applicable, and time_total is end-to-end transfer time.

proxy_used was added in cURL 8.7.0, so check curl --version before adopting that field in a shared job. Treat the metrics as evidence from one request, not a performance benchmark. Record the cURL version, operating system, timestamp, destination you control, proxy mode and exit code alongside them.

Use an Error Ladder Instead of Random Flag Changes

Start at the first layer that failed and stop once the evidence leaves your control. Exact text varies by cURL build, TLS backend and operating system, but the numeric exit code is designed for automation.

EvidenceLayer to inspectNext safe check
curl: (5) Could not resolve proxyLocal resolution of the proxy hostnameVerify the gateway spelling and resolver from the same worker.
curl: (7) Failed to connectTCP path to proxy host and portCheck port, egress firewall and whether the service is listening.
407 plus Proxy-AuthenticateProxy authenticationCheck --proxy-user, authentication scheme and documented username flags.
CONNECT denied or curl: (56)HTTP tunnel establishment or connection resetPreserve the proxy response and test one allowed destination; do not change identity to bypass a refusal.
curl: (97)Proxy handshakeCheck SOCKS version, authentication and address mode. The localhost SOCKS5 lab intentionally returned this after capturing the request.
curl: (28)Configured time budget expiredCompare connect and total timing, then test once with a justified larger budget.
curl: (35) or (60)TLS negotiation or certificate verificationIdentify whether TLS is failing to an HTTPS proxy or inside the destination tunnel; inspect trust configuration rather than disabling it.
Destination 401, 403 or 429Destination authentication, authorization or rate controlStop, use the official API or approved access path, and honor the source's policy and Retry-After.

--insecure is not a general proxy fix. It suppresses certificate verification and can hide interception or a misconfigured endpoint. Use a scoped CA option for a controlled private environment when appropriate, and keep verification enabled for production traffic.

Set Timeouts and Retries From the User Job

--connect-timeout limits the connection phase, including relevant DNS, TCP and TLS work. --max-time limits one transfer. If retries are enabled, --retry-max-time provides a separate overall retry window. A bounded diagnostic request might use --connect-timeout 5 --max-time 20, but those numbers are examples, not universal service objectives.

cURL retries a defined set of transient failures with --retry and honors Retry-After when present. Do not apply --retry-all-errors by default: cURL documents it as a broad option that can duplicate sent or received data. Limit automatic retries to idempotent, authorized operations whose failure semantics you understand. Do not rotate a proxy session in response to 401, 403, 407, CAPTCHA, quota or account controls.

# Example for an approved idempotent health check only
curl --retry 2 \
  --retry-max-time 30 \
  --connect-timeout 5 \
  --max-time 10 \
  --proxy http://gw.databay.co:8888 \
  --proxy-user "$DATABAY_PROXY_USER:$DATABAY_PROXY_PASS" \
  https://health.example.test/

For production, log the attempt count, original session identifier and the final evidence. A new exit should represent an explicit sampling or resilience policy, not an automatic way around a destination decision.

Add Databay Pool, Country and Session Controls Last

First prove that the base gateway and credential work. Then add one documented routing control at a time to the username so a failure has one new variable:

# Base residential route
DATABAY_PROXY_USER='USER-zone-residential'

# Request a US exit
DATABAY_PROXY_USER='USER-zone-residential-countryCode-us'

# Request continuity for an authorized short-lived workflow
DATABAY_PROXY_USER='USER-zone-residential-countryCode-us-sessionId-qa-us-01'

Country selection requests an exit estimate from the chosen pool; it does not reproduce every localization signal. A sticky session requests temporary route continuity; it is not a dedicated device or identity. Verify the observed exit and country using a controlled endpoint, then run the authorized job without changing the session mid-transaction.

Choose datacenter proxies when a permitted workload values throughput and stable infrastructure, or residential proxies when the test genuinely needs a consumer-network route or country sample. If the destination provides an official API, export, preview or regional testing tool that solves the job, use that first.

A Five-Minute Preflight Checklist

  1. Run curl --version and record the exact build and TLS backend.
  2. Neutralize an inherited NO_PROXY only for the explicit test.
  3. Use a harmless destination you control and one request with no redirects or retries.
  4. Keep the proxy address, proxy credentials and destination credentials separate.
  5. Capture exit code, response code, proxy_used when supported, socket peer and timing.
  6. Classify the first failed layer: resolution, TCP, proxy auth, CONNECT or SOCKS, destination TLS, then destination HTTP.
  7. Redact Proxy-Authorization, cookies, tokens, query secrets and response data before sharing a trace.
  8. Stop on unclear permission, authentication boundaries, 403, 429, CAPTCHA or account enforcement.

When the command works but you need to confirm what the gateway actually observed, use the proxy checker methodology for point-in-time liveness and protocol evidence, then use the browser-only proxy format converter to translate a credential safely between supported client formats. Neither tool can prove that a proxy is trustworthy or appropriate for a destination.

Troubleshooting desk

Questions specific to cURL

How do I use a proxy with cURL?
Pass the gateway with --proxy and its credentials with --proxy-user. Keep the destination URL separate, add bounded connection and transfer timeouts, and verify the observed exit through a harmless endpoint you control.
Why does cURL return 407 Proxy Authentication Required?
A proxy generated a challenge because credentials were missing, invalid, partial or sent with the wrong authentication method. Check --proxy-user rather than --user, inspect Proxy-Authenticate locally, and verify documented username routing flags.
Does an HTTP proxy protect an HTTPS request?
cURL normally uses HTTP CONNECT to create a tunnel, then performs destination TLS through that tunnel. The destination TLS remains end to end, while the client-to-proxy control hop is plain HTTP unless the proxy URL itself uses https:// and the cURL build supports HTTPS proxies.
What is the difference between socks5:// and socks5h:// in cURL?
With socks5://, cURL resolves the destination hostname locally and sends an IP address to the proxy. With socks5h://, cURL sends the hostname in the SOCKS5 request and asks the proxy to resolve it.
How can I keep proxy credentials out of shell history?
Inject them from a secret manager and stream a config to curl --disable --config - so the expanded password is not a cURL argument. Avoid shell tracing and understand that standard input and environment variables are still process memory, not universal secret stores.
Does remote_ip in --write-out show the proxy exit IP?
Usually not. It identifies the peer socket cURL connected to, which is the gateway when a proxy is used. An approved destination endpoint must report the source address it observed if you need point-in-time exit evidence.
Adjacent runbooks

Same gateway, different control surface

  • Axios

    HTTP client library

    Axios request -> route selector -> absolute-form or CONNECT -> hop evidence

  • Node.js fetch

    HTTP client library

    fetch -> env opt-in or same-package dispatcher -> proxy evidence

  • Python Requests

    HTTP client library

    Session -> HTTPAdapter policy -> proxy hop -> approved destination

  • Incogniton

    Multi-profile browser

    Profile editor -> Databay gateway -> pinned residential exit

  • Playwright

    Browser automation

    Browser process -> isolated contexts -> independent exit sessions

  • Puppeteer

    Browser automation

    --proxy-server -> page.authenticate() -> page.goto()

  • Scrapy

    Crawler framework

    Request queue -> downloader middleware -> rotating exit pool

  • Selenium

    Browser automation

    WebDriver -> auth decision -> Databay gateway

Choose the exit pool after the control path works. Use residential for reputation-sensitive targets or datacenter for throughput.

Residential →Datacenter →

Ship cURL to production

Create an account, drop in your gateway credentials, and route your first cURL request in minutes.

Pricing, order minimums, and traffic validity vary by product.