A successful curl request does not show that your Python application used the same proxy. Compare the destination, the configuration visible to each process, and the server that actually received the request. Only then use the application's result to accept or reject a proxy integration.

This guide is for developers moving an authorized collection or regional QA job into a worker, container or scheduled process. The immediate decision is whether an apparent proxy failure belongs to the application's route configuration. Buying another plan before resolving that question can leave the same problem in place.

Write down the route you intended to test

For one harmless request, name the destination scheme and host, the approved proxy configuration identifier, the client library and version, and the launch method. A terminal command, an IDE run and a scheduled worker are separate test environments. Record whether each process has the relevant variables, without copying their credential-bearing values into shared logs.

Record for each processExample of a safe descriptionWhy it changes the decision
Target and scopeControlled HTTP health target, one GET, no redirectsA success against another host or scheme does not validate this request.
Launch environmentTerminal or worker, deployment revision, variable names presentA setting in one process may be absent from the actual job.
Configuration ownerEnvironment, Session settings, or per-request mappingThe file someone edited may not supply the effective value.
Exclusion decisionApproved direct route or required proxy route for this targetA direct response can be correct or a failed acceptance gate.
Observed receiverControlled target/proxy marker and request identifierHTTP 200 alone cannot distinguish the two paths.
OutcomeExpected path matched, mismatched, or unknownUnknown remains a hold, rather than an assumed supplier failure.

Reproduce the difference without a paid endpoint

Download the local curl/Requests route experiment. It uses local marker servers so that a direct request and a proxy-selected request can both return successfully while identifying different receivers. The mock proxy returns its own response and never forwards the request. No IPHTML account, real proxy password or external target is needed.

The experiment's exact environment, cases and results appear below. Its scope is plain HTTP to a loopback address. A local receiver marker proves client-side selection within this experiment. It does not prove an upstream exit address, remote forwarding, TLS, SOCKS, regional content, throughput or long-term stability.

Tested on November 4, 2026 with Python 3.9.6, Requests 2.32.5, urllib3 2.6.3 and curl 8.7.1 on macOS. Each client gets a controlled process environment and an empty temporary home directory. curl starts with -q to skip its default configuration. The Requests child rejects connections outside the two allocated loopback ports. Both clients use one fixed URL without redirects. Native system proxy settings are not changed or neutralized. The direct-path rows are observations from this run, not a promise that removing environment variables forces every machine to connect directly. An unexpected platform proxy can make the guarded test fail.

python3 -m venv .venv
.venv/bin/python -m pip install 'requests==2.32.5' 'urllib3==2.6.3'
.venv/bin/python curl-python-proxy-route-checks.py

Dependency installation uses the package registry. The experiment itself sends only local HTTP requests. Python 3.9.6 on this machine reported an urllib3/LibreSSL compatibility warning. The HTTP matrix completed, but no HTTPS/TLS compatibility result is claimed. Record your own interpreter and library versions when repeating it.

Controlled casecurl receiverRequests receiverInterpretation
No proxy variables or explicit proxyTargetTargetDirect path observed in this run.
Only uppercase HTTP_PROXYTargetProxy markerThe same variable does not select the same HTTP route.
Only lowercase http_proxyProxy markerProxy markerThe two clients agree in this case.
Lowercase proxy plus NO_PROXY=127.0.0.1TargetTargetThe local target matches the environment exclusion.
Lowercase proxy, but Requests uses trust_env=FalseProxy markerTargetThe application's environment policy changes the selected path.
Explicit proxy in each client, plus NO_PROXY=127.0.0.1TargetProxy markercurl --proxy and Requests' per-request mapping do not have identical exclusion precedence here.
Parent has lowercase proxy; sanitized child environments omit itTargetTargetA parent setting does not establish a deliberately filtered child's configuration.

The program asserts both the receiving marker and the HTTP request form. The target receives /route; the proxy marker receives an absolute HTTP URL. All seven cases return HTTP 200. That is precisely why status alone would hide these route differences. A failed assertion or unavailable dependency means the experiment did not pass on that environment; inspect it rather than treating the table as a guarantee for all runtimes.

What the differences tell you

curl deliberately accepts the HTTP proxy environment setting only in its lowercase form, http_proxy. Its uppercase treatment for other schemes is different. The curl environment documentation explains the HTTP exception and exclusion rules. Do not turn the result of an uppercase-only HTTP test into a rule about HTTPS.

Requests can combine environment values with application settings. Its proxy documentation warns that environment proxies can override session.proxies, and distinguishes a per-request proxies argument. An exclusion in the environment is not a universal network enforcement mechanism. The experiment checks specific call paths, rather than assuming every client gives NO_PROXY the same precedence.

Session.trust_env=False is a diagnostic change with a wider effect than proxy selection. It also changes Requests' use of environment CA-bundle settings and default netrc authentication. If your approved HTTPS setup requires a private CA, provide the trusted certificate configuration explicitly and keep verification enabled. Do not copy this switch into production merely because a local test passed.

Compare the actual worker with the terminal

  1. Freeze one approved request. Hold the URL, method, client version and request options constant. Disable redirects for the diagnostic test so another host cannot silently become the comparison target. Keep the production workflow's required route policy in view.
  2. Check configuration inside each process. A parent shell's settings are not proof of what an already-running worker received. Record variable presence, an approved endpoint alias, configuration revision and the point where the client object is created. Do not print the full environment.
  3. Inspect application overrides. Check the actual Session and request arguments, wrappers and transport adapters used by the job. Establish which layer owns the route. Keep environment-driven and explicit-configuration tests separate so the evidence has one explanation.
  4. Observe both ends you control. Correlate a safe request identifier with permitted proxy or target observations. A public IP-check result for a different destination is insufficient. If the intended route is mandatory and the observation is direct or uncertain, stop the trial and correct the integration.
  5. Repeat after the relevant deployment change. Restart or redeploy through your normal process if that is how the worker receives configuration. Confirm the real worker's result, then proceed to the workload trial. Record a timeout as a failure with route unknown unless another observation establishes the receiver.

Do not “fix” a route mismatch by deleting an organization's exclusions or forcing a proxy around a required control. Ask the route owner which path is permitted. If an approved direct API or licensed feed already supplies the required data, that can be the correct integration without buying proxy capacity.

Set a purchase gate that this test can support

Pass this gate only when the actual application uses its approved route for the required request and the result can be reproduced after the relevant restart or deployment. A terminal-only success, a receiver mismatch, or an unexplained route stays on hold. Passing this gate makes the workload evaluation meaningful; it does not establish a provider's suitability.

Keep the next checks separate. The Python setup tutorial covers basic Requests and SOCKS configuration. The aiohttp integration guide covers async client and connector boundaries. Use the representative trial guide for workload coverage and acceptance criteria once the route is understood.

For an IPHTML evaluation, take the permitted target category, required protocol, deployment runtime and redacted route record to the integration documentation. Review the current residential proxy options only if the workload requires that kind of route. If endpoint behavior is unclear, ask support with the redacted record. Confirm current product terms separately. This experiment makes no claim about IPHTML performance, price, capacity or trial allowance.

Sources checked November 4, 2026. curl proxy environment variables, the curl manual for command and exclusion behavior, and Requests Session implementation for environment merging and its scope. Online documentation can describe a newer version than the tested runtime. The downloaded experiment and named local results are the evidence for the matrix on this page.