A request can work through session.get() and fail certificate verification after being rewritten as a PreparedRequest. The low-level send path does not run the same environment merge as the normal request method.

import requests

with requests.Session() as session:
    request = requests.Request("GET", "https://example.com/")
    prepared = session.prepare_request(request)

    settings = session.merge_environment_settings(
        prepared.url, {}, None, None, None
    )
    response = session.send(
        prepared,
        timeout=(5, 15),
        **settings,
    )
    response.raise_for_status()
    print(response.status_code)

Merge using the final prepared URL, after any intended URL changes. Proxy and bypass decisions depend on the destination, so settings gathered for an earlier URL may be wrong for the request you actually send.

The CA setting is an easy part to miss

With normal environment trust enabled, merging considers REQUESTS_CA_BUNDLE and its CURL_CA_BUNDLE fallback when verification has not been explicitly overridden. Calling send directly with the default verify setting does not perform that CA lookup. Turning verification off hides the discrepancy instead of supplying the intended certificate store.

Session.prepare_request() also applies the session's preparation behavior. Creating a request with Request.prepare() directly is a separate choice; do not expect it to apply session cookies or other session preparation automatically.

Proxies have a more specific rule

It would be inaccurate to say that every PreparedRequest ignores proxy environment variables. In Requests 2.34.2, send resolves proxy defaults when its proxies keyword is absent. Supplying proxies={} to send skips that particular default-resolution branch.

The empty dictionary passed to merge_environment_settings has a different role: the merge can populate it with applicable environment routes before it is forwarded to send. Looking only at the presence of an empty dictionary in two snippets misses the different methods receiving it.

For custom request-building code, keep preparation, environment merging, and sending together. When the application intentionally uses trust_env=False, the merge honors that policy; it is not a way to force environment settings into a client that deliberately disabled them.

Artihkkalat mat laktásit