Go's environment proxy selector has a built-in exception for localhost and loopback IP destinations. Clearing NO_PROXY does not remove that exception. This can make a local test go direct while a request to a public hostname uses the proxy as expected.

The rule concerns the request's destination. It does not prevent you from using a proxy listener whose own address is 127.0.0.1.

Inspect the selector without sending a request

package main

import (
    "fmt"
    "net/http"
    "net/url"
)

func main() {
    fixed, _ := url.Parse("http://203.0.113.10:8080")
    for _, target := range []string{
        "http://localhost:8000/",
        "http://127.0.0.1:8000/",
        "http://example.com/",
    } {
        request, _ := http.NewRequest("GET", target, nil)
        discovered, err := http.ProxyFromEnvironment(request)
        explicit, _ := http.ProxyURL(fixed)(request)
        fmt.Println(target, discovered, explicit, err)
    }
}

Run it with proxy variables set for the process if you want to observe the environment comparison. The program evaluates selectors only; it does not connect to the documentation proxy or any of the destinations.

Environment discovery and an explicit selector are different policies

ProxyFromEnvironment considers the destination scheme, environment settings, and bypass rules, including its special loopback handling. ProxyURL returns the supplied proxy URL for every request passed to that selector.

A dedicated transport with an explicit ProxyURL can therefore send a local destination through a proxy. That is useful only when the proxy can legitimately reach the requested destination. A remote proxy's localhost is not your laptop's localhost, so forcing the route is not automatically a useful connectivity test.

Check before the process has cached its environment

The standard net/http environment proxy configuration is cached after its first use. Changing an environment variable later inside the same running program is not a reliable way to repeat a fresh configuration test. Start a new process with the intended values, or supply an explicit selector whose behavior you control.

This loopback behavior applies to Go 1.27.3’s standard proxy selector. Other languages and HTTP clients can use different localhost routing rules.

Erthyglow kevrennek