NO_PROXY has no standard grammar, and the clients that read it disagree on most of it. In the main matrix of a loopback lab run on 23 September 2026, 15 clients received identical no_proxy and NO_PROXY values: two curl builds, wget, Go, five Python clients and six Node.js configurations. Of 49 value-and-request combinations in the main matrix, 21 routed the same way in every client and 28 did not. Every cell is in the published results.csv, one row per client and request.
If one value has to serve all of them, use only the shapes that behaved identically everywhere, and give both variable names the same value:
# example.com and 192.0.2.10 stand for your own domain and address
export no_proxy="localhost,127.0.0.1,example.com,.example.com,192.0.2.10"
export NO_PROXY="$no_proxy"- The pair
example.com,.example.com(tested asexample.test,.example.test) was the only spelling that covered a domain and all of its subdomains in all 15 clients. It never matchednotexample.test. - An exact IPv4 address matched only itself in every client. An IPv4 CIDR range worked in only 4 of the 15.
localhost,127.0.0.1bypassed the proxy for127.0.0.1andlocalhostin every client. Without loopback entries, only Go skipped the proxy for loopback.- wget reads only
no_proxy. Go 1.27.1'snet/httpprefersNO_PROXYwhen both are set, and Go 1.28 is due to preferno_proxyinstead. Keep the two names identical.
The published dataset tests these entries in separate cases. In a one-off run of the exact line above, with example.test in place of example.com, each of its nine test requests also routed the same way in all 15 clients.
Two kinds of spelling cause trouble. Some break a client or turn a list off. A bracketed IPv6 entry makes httpx and httpx2 fail when the client is created, and so does an IPv6 CIDR entry in httpx 0.28.1. An empty lowercase no_proxy next to a set NO_PROXY switched the list off in 9 clients. Others are silently ignored by some clients: *.example.com by 8, * inside a list by 9, an IPv4 CIDR range by 11, a trailing dot by 11, a space-separated list by 9, and a host:port entry by 4 to 6, depending on its form. Even a bare * is ignored by wget.
These results are synthetic. They come from one Mac, a proxy on 127.0.0.1, reserved .test names and documentation IP addresses, and they describe how the pinned client versions choose a route, not how any proxy service behaves. For how each client reads the proxy variables in the first place, see how clients read HTTP_PROXY and NO_PROXY. If Node's fetch() ignores the proxy completely, start with Fix Node.js TypeError: fetch failed behind a proxy.
The portable subset and the spellings to avoid
The tables use the names the lab requested: example.test, sub.example.test, a.b.example.test and notexample.test. No client here resolves a host name before deciding: their source code compares names as text, and curl, Go and Requests parse an IP address in the URL for CIDR checks. None of the 662 proxied requests triggered a recorded sandbox denial for a DNS lookup or connection, although the kernel log drops some denial lines. Real domain names should therefore behave like these.
The 15 clients, each reading the proxy variables from the environment with the settings shown, were:
- curl 8.7.1 (macOS) and curl 8.22.0;
- GNU Wget 1.25.0;
- Go 1.27.1
net/httpwithhttp.ProxyFromEnvironment; - Python 3.14.7
urllib, requests 2.34.2, httpx 0.28.1, httpx2 2.13.1 and aiohttp 3.14.3 withtrust_env=True; - Node.js 26.10.0 and 24.21.0 built-in
fetch()andhttp.get(), each withNODE_USE_ENV_PROXY=1(called "Node 26 fetch", "Node 26 http" and so on below); - npm undici 7.29.1 and 8.11.0
fetch()withdispatcher: new EnvHttpProxyAgent(), both on Node 26.10.0.
These entries gave the same result in all 15 clients for the requests shown:
| Entry | Result in every client |
|---|---|
example.test | Bypassed example.test; notexample.test still used the proxy (subdomains differed in Node's http client) |
.example.test | Bypassed sub.example.test and a.b.example.test (the apex differed in 4 clients) |
example.test,.example.test | Bypassed the apex and both subdomains; notexample.test still used the proxy |
192.0.2.10 | Bypassed that address; 192.0.2.11 still used the proxy |
EXAMPLE.TEST, or a request to EXAMPLE.TEST | Letter case made no difference |
other.test , example.test | A space after a comma made no difference |
other.test,,example.test or other.test,, | Empty items matched nothing |
localhost,127.0.0.1,::1 | Bypassed 127.0.0.1 and localhost ([::1] differed; see the loopback section) |
no_proxy set, NO_PROXY unset | Every client read the lowercase variable |
Each spelling to avoid from the answer above has its own section below, with the clients that diverged.
NO_PROXY wildcard: does *.example.com match example.com?
It depends on the client, and 8 of 15 did not treat it as a wildcard at all. With NO_PROXY=*.example.test:
| Request | Bypassed the proxy | Used the proxy |
|---|---|---|
example.test | Node 26 fetch, Node 24 fetch, undici 7.29.1 | The other 12 |
sub.example.test, a.b.example.test | Go, Node 26 and 24 fetch and http, undici 7.29.1 and 8.11.0 | curl (both), wget, urllib, requests, httpx, httpx2, aiohttp |
notexample.test | None | All 15 |
curl, wget and all five Python clients matched nothing with this entry. Go, Node's http client and undici 8.11.0 read it as "subdomains only", and Node's built-in fetch() and undici 7.29.1 also bypassed the apex.
The apex split between Node 26's built-in fetch() and npm undici 8.11.0 is new. undici PR #5777, released in undici 8.11.0 on 22 September 2026, says a *.domain entry "must only match sub.example.com / a.b.example.com, not the apex". Node 26.10.0 still bundles undici 8.10.2. So on the same Node 26.10.0 runtime, built-in fetch() bypassed example.test and npm undici 8.11.0 sent it to the proxy. The same pull request made * work inside a list or with spaces around it, which accounts for the only other rows where those two clients differed.
For subdomains in every client, write .example.com. Add example.com if the apex should bypass too. No tested spelling kept the apex on the proxy in all 15 clients while bypassing its subdomains.
Leading dot vs bare domain: .example.com, example.com and subdomains
| Entry and request | Bypassed the proxy | Used the proxy |
|---|---|---|
example.test, request sub.example.test | 13 clients | Node 26 http, Node 24 http |
.example.test, request example.test | 11 clients | wget, Go, httpx, httpx2 |
A bare domain matched its subdomains everywhere except in Node's built-in http client, which matched example.test exactly. The lab reproduced node#65616, first reported on Node 24.18.1, on 26.10.0 and 24.21.0. Node's own NO_PROXY format list calls example.com an "Exact host name match", which describes http.request(), not fetch(). A fix, node#65617, was still open on 23 September 2026.
A leading dot matched every subdomain in every client, but wget, Go, httpx and httpx2 did not apply it to the apex. Go documents this: a domain name with a leading dot "matches subdomains only" (httpproxy).
Neither entry matched notexample.test in any client. Requests has enforced that label boundary only since 2.34.0; its release notes say it "no longer performs greedy matching on no_proxy domains". Older Requests versions were not tested.
NO_PROXY=* and * inside a list
| Value | Bypassed the proxy | Used the proxy |
|---|---|---|
* | 14 clients | wget |
other.test,* or " * " | Go, httpx, httpx2, Node 26 http, Node 24 http, undici 8.11.0 | curl (both), wget, urllib, requests, aiohttp, Node 26 fetch, Node 24 fetch, undici 7.29.1 |
* works as the entire value, with no spaces, in every client except wget. curl documents it that way: "The only wildcard available is a single * character" (CURLOPT_NOPROXY). wget 1.25.0 has no wildcard. To keep one wget command off the proxy, use its --no-proxy option (wget manual).
CIDR, IP ranges and subnets in NO_PROXY
With NO_PROXY=192.0.2.0/24, a request to 192.0.2.10 bypassed the proxy in curl 8.7.1, curl 8.22.0, Go and requests. The other 11 sent it to the proxy: wget, urllib, httpx, httpx2, aiohttp and all six Node clients. 198.51.100.10, outside the range, used the proxy in every client. No client raised an error for the IPv4 range; the 11 without support ignored it.
- curl added CIDR support in 7.86.0 (changelog).
- Requests checks CIDR in its own matcher before falling back to urllib, which is why the two Python clients differ.
- httpx and httpx2 accepted the entry without matching the range. httpx2 PR #1165, which would add CIDR ranges, was open on 23 September.
- Node's NO_PROXY format list documents a dash range such as
192.168.1.1-192.168.1.100instead of CIDR. The lab did not test dash ranges. A node#57872 comment reports that a dash range worked innode:httpbut not infetch()on a v27 pre-release.
To keep a subnet off the proxy in a mixed stack:
- List the exact addresses your clients call. Exact IPv4 addresses were the only form that matched in all 15.
- An IPv4 range can be added next to them for curl, Go and Requests. With
192.0.2.10,192.0.2.0/24, a one-off run outside the published dataset bypassed192.0.2.10in all 15 clients and192.0.2.11only in those 4; no client raised an error. Leave IPv6 ranges out, because httpx 0.28.1 fails on them (see below). - A range applies only to an IP address written in the URL. curl, Go and Requests do not resolve a host name first, so
192.0.2.0/24does not cover a name that resolves into it. This comes from their source code; the lab used IP addresses only.
IPv6 in NO_PROXY: bare, bracketed and CIDR
For a request to http://[2001:db8::10]/:
| Entry | Bypassed the proxy | Did not bypass |
|---|---|---|
2001:db8::10 | 12 clients | urllib, Node 24 fetch, undici 7.29.1 used the proxy |
[2001:db8::10] | urllib, Node 26 fetch, Node 24 fetch, undici 7.29.1, undici 8.11.0 | 8 used the proxy; httpx and httpx2 raised an error |
2001:db8::/48 | curl 8.22.0, Go | 12 used the proxy; httpx raised an error |
[2001:db8::10]:8080, request on port 8080 | Go, urllib, Node 26 fetch, Node 24 fetch, undici 7.29.1, undici 8.11.0 | 7 used the proxy; httpx and httpx2 raised an error |
The bare form did best: it matched in 12 clients and broke none. curl asks for it: "Enter IPv6 numerical addresses in the list of hostnames without enclosing brackets" (CURLOPT_NOPROXY). undici added bare IPv6 matching in 8.10.0 (PR #5623); undici 7.29.1, which Node 24.21.0 bundles, does not have it.
Of the two curl builds, only 8.22.0 matched the IPv6 range. Before 8.18.0 (curl#19828), curl's matcher treated a host as IPv6 only when it arrived in brackets, which it never does, so an IPv6 CIDR entry could not match.
httpx InvalidURL: Invalid port from a bracketed IPv6 entry
A bracketed entry is worse than ignored in httpx 0.28.1 and httpx2 2.13.1. Creating a client with default environment handling raised InvalidURL: Invalid port: 'db8::10]' before any request was sent. With NO_PROXY=localhost,127.0.0.1,[::1], the error was Invalid port: ':1]', and requests to 127.0.0.1 and localhost failed as well, because the client was never created. httpx 0.28.1 raised the same way for 2001:db8::/48 (Invalid port: 'db8::'). httpx2 2.5.0 stopped that crash ("Allow IPv6 CIDR notation in no_proxy", changelog), but as the table shows, it still did not match the range.
To fix it, write IPv6 entries without brackets, such as ::1 or 2001:db8::10; both clients were created normally with those. Keep IPv6 ranges out of any value httpx 0.28.1 reads. If you cannot change the variable, create that client with trust_env=False, which was also created normally, and pass its proxy in code, as the HTTPX proxy guide does. That client then ignores all the proxy variables.
Ports in NO_PROXY: host:port
For a request on the listed port 8080:
| Entry | Bypassed the proxy | Used the proxy |
|---|---|---|
example.test:8080 | 11 clients | curl (both), wget, aiohttp |
192.0.2.10:8080 | 10 clients | curl (both), wget, requests, aiohttp |
.example.test:8080 | 9 clients | curl (both), wget, aiohttp, Node 26 http, Node 24 http |
On port 80, all three entries used the proxy in every client, so no client applied a port entry to a different port. The failure was the opposite: some clients never matched the entry at all. curl's documentation describes no port syntax for entries, and wget compares the host name only. aiohttp passes the host without its port to urllib's matcher (source). Requests never matched an IPv4 entry that includes a port: with 192.0.2.10:8080, it used the proxy on port 8080 as well as on port 80. Its IPv4 check compares only the host, according to PR #7586, a fix that was still open on 23 September.
Keep ports out of a shared value. If one port must bypass the proxy, configure that bypass in the client that needs it.
Spaces, empty items, trailing dots and uppercase
- Space before a comma: with
example.test ,other.test, wget kept the trailing space as part of the entry and sentexample.testto the proxy. The other 14 bypassed it. - Spaces instead of commas: with
other.test example.test, curl 8.7.1, Node 26 fetch, Node 24 fetch, undici 7.29.1 and undici 8.11.0 bypassed both hosts. curl 8.22.0 bypassed onlyother.test. The other 9 bypassed neither. curl 8.9.0 made the change: "noproxy: patterns need to be comma separated" (changelog). - Empty items:
other.test,,did not bypassexample.testin any client, so no client treated an empty item as "match everything". - Trailing dots: an
example.test.entry, or a request tohttp://example.test./, matched only in curl 8.7.1, curl 8.22.0, Node 26 fetch and undici 8.11.0. undici added this in 8.10.1 (PR #5637), so Node 24 fetch and undici 7.29.1 do not have it. - Uppercase: entries and hosts in capitals matched in all 15 clients.
NO_PROXY vs no_proxy: which one wins, and the empty-variable trap
For a request to example.test:
| Environment | Bypassed the proxy | Used the proxy |
|---|---|---|
NO_PROXY=example.test only | 14 clients | wget |
no_proxy=example.test only | All 15 | None |
NO_PROXY=example.test, no_proxy=other.test | Go 1.27.1 | The other 14 |
NO_PROXY=example.test, no_proxy="" | curl (both), Go, requests, Node 26 http, Node 24 http | wget, urllib, httpx, httpx2, aiohttp, Node 26 fetch, Node 24 fetch, undici 7.29.1, undici 8.11.0 |
When the two names disagree, Go 1.27.1's net/http uses NO_PROXY and the other 14 use no_proxy. An empty lowercase variable splits the clients 6 to 9. curl, Go, requests and Node's http client treat it as unset and fall back to NO_PROXY. The other nine treat it as an empty list. node#66202, opened on 22 September 2026 against a pre-release build, describes this split between fetch() and http.request(). The lab reproduced it on released Node 26.10.0 and 24.21.0.
Go's precedence is changing. golang.org/x/net commit a02ddfa7ea, made for golang/go#79656 and released in x/net v0.58.0, makes the httpproxy package prefer the lowercase names, and the Go 1.28 release-note draft lists the same change for ProxyFromEnvironment. In a separate check, x/net v0.58.0 and v0.59.0 already followed no_proxy in the conflicting case. Go still skips empty values, so its empty-variable results do not change.
The proxy variable has the same trap. With http_proxy="" and HTTP_PROXY set, only Go, Node 26 http and Node 24 http used the proxy; the other 12 went direct. curl reads http_proxy only in lowercase.
Give both names the same value, and remove a variable with unset rather than exporting it empty.
localhost, 127.0.0.1 and ::1: only Go skips the proxy on its own
With no NO_PROXY at all, Go went direct for 127.0.0.1, localhost and [::1]. Its httpproxy package documents that localhost and loopback addresses never use a proxy. The other 14 clients sent all three to the proxy. With a remote proxy configured, those clients would therefore send a request for a local development server to that proxy unless loopback is listed.
| Value | 127.0.0.1 and localhost | [::1] |
|---|---|---|
localhost,127.0.0.1,::1 | Bypassed in all 15 (Go: built-in loopback rule) | Bypassed in 12 (Go: built-in loopback rule); urllib, Node 24 fetch and undici 7.29.1 used the proxy |
localhost,127.0.0.1,[::1] | httpx and httpx2 raised an error; 13 bypassed (Go: built-in loopback rule) | Bypassed in urllib, Node 26 fetch, Node 24 fetch, undici 7.29.1 and 8.11.0, and in Go by its built-in loopback rule; httpx and httpx2 raised an error; 7 used the proxy |
Go's bypasses in this table come from its built-in rule, not from the list, so they do not show that [::1] works as an entry in Go; in the main matrix Go used the proxy for the bracketed entry [2001:db8::10].
List localhost,127.0.0.1. Add a bare ::1 if you use IPv6 loopback, and never [::1].
Does HTTPS through CONNECT get the same bypass decision?
Yes, in this run. For each of 8 HTTPS URLs, every client made the same choice as for the matching HTTP URL, 120 of 120 comparisons. Every proxied HTTPS request arrived at the proxy as CONNECT.
Node.js: NO_PROXY not working with fetch or http.request
Four separate things can make NO_PROXY look broken in Node. The explicit ProxyAgent case comes from undici's documentation and was not tested; the other three are lab results.
The opt-in. Without NODE_USE_ENV_PROXY=1 or --use-env-proxy (docs), Node 26 and 24 fetch() and http.get() ignored the proxy variables and went direct in all 36 control cells. The Node fetch guide covers that failure.
An explicit ProxyAgent. undici's documentation describes a ProxyAgent as routing every request through its proxy and mentions no bypass list; reading no_proxy and NO_PROXY is what EnvHttpProxyAgent adds (undici 8.11.0 docs for ProxyAgent and EnvHttpProxyAgent). Code that passes a ProxyAgent as the dispatcher, as the Node.js fetch proxy setup guide does, therefore ignores NO_PROXY. To keep a bypass list, use new EnvHttpProxyAgent(), which reads the variables or takes httpProxy, httpsProxy and noProxy options.
Two matchers in the same runtime. http.request() uses Node's own matcher, and built-in fetch() uses undici's EnvHttpProxyAgent. They disagreed on 20 of 72 non-baseline rows on Node 26.10.0 and on 19 of 72 on Node 24.21.0. Node's matcher carries the comment TODO(joyeecheung): share code with undici. (source), and sharing that code is still an open item in the tracking issue node#57872.
Bundled vs npm undici. On Node 26.10.0, built-in fetch() (undici 8.10.2) and npm undici 8.11.0 differed on 4 rows, all wildcard cases. Node 24.21.0 fetch() and npm undici 7.29.1 did not differ at all. undici 7.29.1 and 8.11.0 differed on 11 rows.
The table below shows one row for each kind of difference on Node 26.10.0, using the values from the sections above. The other 12 of the 20 differing rows repeat these kinds for other hosts and requests, plus the http_proxy="" case.
| Difference | fetch | http | undici 8.11.0 |
|---|---|---|---|
| Bare domain, subdomain request | Bypassed | Proxy | Bypassed |
*.example.test, apex request | Bypassed | Proxy | Proxy |
* inside a list | Proxy | Bypassed | Bypassed |
| Bracketed IPv6 address | Bypassed | Proxy | Bypassed |
| Leading dot with a port | Bypassed | Proxy | Bypassed |
| Trailing-dot entry | Bypassed | Proxy | Bypassed |
| Spaces instead of commas | Bypassed | Proxy | Bypassed |
Empty no_proxy, NO_PROXY set | Proxy | Bypassed | Proxy |
Node 24.21.0 showed the same pattern, with two exceptions. For the trailing dot, both of its clients used the proxy. For a bare IPv6 entry, only http bypassed it.
A 2026-09-01 comment on node#57872 already compared node:http with fetch() on a v27.0.0 pre-release build. The lab's Node rows agree with all 8 rows of that table that it could compare.
What GitLab found in 2021, and what changed
GitLab's 2021 post by Stan Hu, with research by Nourdin el Bacha, compared curl, wget, Ruby, Python, Go and Java from their source code and documentation. It recommended a lowest common denominator and proposed a standard.
Of the 32 cells in its no_proxy table that this lab could check (8 rows for curl, wget, Python via urllib and Go), 31 still match. The exception is curl and CIDR: the 2021 table says no, but both curl builds honored it here. Go's "Uppercase" precedence cell still matches Go 1.27.1 and is due to change in Go 1.28. The lab could not check the rows "Supports regexes?" and "Resolves IP addresses?"; the second marks Go "Yes", but the post's own text says only Ruby resolves host names, and Go 1.27.1's source does not. Ruby and Java were not tested.
Its lowest-common-denominator advice holds up only in part. A lowercase-only no_proxy, commas and exact IPv4 addresses worked in all 15 clients, a leading dot still missed the apex in 4, as the post warned, and only 4 honored IPv4 CIDR, so avoiding CIDR is still sound. "Suffixes are always matched" failed in Node's http client, "comma-separated hostname:port values" matched in only 9 to 11 clients per entry (8 matched all three), and no IPv6 form agreed.
Several of these behaviors are recent. Requests 2.34.0 (11 May 2026) added the label boundary. httpx2 2.5.0 (25 June 2026) stopped crashing on IPv6 CIDR entries without matching them. undici 8.10.0, 8.10.1 and 8.11.0 (August and September 2026) added bare IPv6, trailing dots and the new wildcard rules.
How the test works, and how to rerun it
A small HTTP proxy on 127.0.0.1 logged every absolute-form request and every CONNECT, answered it itself and forwarded nothing. Each request ran in its own process under macOS sandbox-exec, with a profile that denies all outbound traffic except loopback, so a direct attempt failed on the machine and reached no real host. A cell counts as proxied only when the proxy logged its request; whether the client got a response never decided anything. With no NO_PROXY set, all 15 clients proxied every URL shape.
The published run, on 23 September 2026 from 19:13 to 19:15 UTC, has 1,266 cells. A clean rerun that followed the steps below from the published archive classified all 1,266 cells identically.
To read the published matrix without running anything, extract the archive and run python3 no_proxy_lab.py table results.json. It needs no setup or network, and it printed the same output on Python 3.9.6 as on 3.14.7. A full rerun needs macOS, Python 3.14 and Go, about 700 MB of disk, and access to nodejs.org, pypi.org and registry.npmjs.org during setup, which installs nothing system-wide:
curl -fLO https://ipvolt.com/downloads/no-proxy-matching-tested/no-proxy-matching-tested.zip
unzip no-proxy-matching-tested.zip
cd no-proxy-matching-tested
python3.14 no_proxy_lab.py setup --work ./work
python3.14 no_proxy_lab.py run --work ./work --out ./out
python3.14 no_proxy_lab.py compare results.json out/results.json
python3.14 no_proxy_lab.py table out/results.json --section maincompare exits 0 only when every cell has the same classification. The README explains its output with other client builds, how to test other versions or your own NO_PROXY value, the --isolation none mode for other systems, and every field of results.json.
Downloads:
- no-proxy-matching-tested.zip: every file below, with
clients/in place (recreate it if you download files one at a time) - README.md: method, requirements, commands and how to read the results
- results.json and results.csv: every cell of the published run
- no_proxy_lab.py, clients/py_client.py, clients/node_client.cjs, clients/go_client.go and nonet.sb: the harness, the one-request clients and the loopback-only sandbox profile
- requirements.txt, package.json and package-lock.json: exact Python and npm pins
Limits
- One macOS 15.7.4 arm64 machine, one date and the versions above. Any release can change a row: Node 26.10.0 does not yet bundle undici 8.11.0, and Go 1.28 is due to change the conflicting-variable row.
- Linux was not tested. Each client matches NO_PROXY in its own code or its language's standard library, and with the proxy variables set, Python's urllib takes the same environment path on macOS as on Linux. On Linux the rows should therefore follow the client version rather than the operating system. That is an inference from the source code, not a Linux result; the README gives examples.
- The matrix tested only environment-variable handling, with the settings listed above, and only HTTP forward proxying. It did not test explicit proxy options, other agents or dispatchers, system proxy settings, Windows, SOCKS, PAC files, redirects or proxy authentication. For a 407 response, see how to fix proxy error 407.
- Dash ranges, partial addresses such as
192.168.*, entries that depend on DNS resolution, and Ruby, Java, .NET, Deno and Bun were not tested; the README lists the rest. - The two one-off checks above ran on 24 September 2026 with the same harness and clients. They are not in
results.json; the README shows how to rerun them.
ipvolt ran these checks locally on 23 and 24 September 2026 with the client versions listed above. No external provider, proxy service or network was tested, and nothing here describes ipvolt's own service.
If you want to hear when ipvolt access opens, join the early-access list. One email when access opens. Nothing else.
Sources
- GitLab (2021): We need to talk: Can we standardize NO_PROXY?
- nodejs/node#57872: node:http vs fetch() NO_PROXY table (comment, 2026-09-01)
- nodejs/node#65616: NO_PROXY=example.com and http.request() subdomains
- nodejs/node#65617: http: match subdomains for plain NO_PROXY entries
- nodejs/node#66202: fetch() and http.request() with an empty lowercase variable
- Node.js 26.10.0 docs: NO_PROXY format
- Node.js 26.10.0 docs: NODE_USE_ENV_PROXY
- Node.js 26.10.0 source: lib/internal/http.js (http.request matcher)
- Node.js 26.10.0: bundled undici version
- undici PR #5777: NO_PROXY wildcard semantics
- undici v8.11.0 release notes
- undici PR #5623: match bare IPv6 addresses in no_proxy
- undici PR #5637: ignore trailing dots when matching no_proxy
- undici v8.11.0 docs: ProxyAgent
- undici v8.11.0 docs: EnvHttpProxyAgent
- libcurl: CURLOPT_NOPROXY
- curl changelog
- curl#19828: IPv6 CIDR notation in NO_PROXY (fixed in 8.18.0)
- Go: golang.org/x/net/http/httpproxy Config
- Go: httpproxy Config.ProxyFunc (localhost and loopback)
- golang.org/x/net commit a02ddfa7ea: httpproxy prefers lowercase proxy variables (x/net v0.58.0)
- golang/go#79656: inconsistent HTTP_PROXY precedence (milestone Go 1.28)
- Go 1.28 release-note draft: ProxyFromEnvironment prefers lowercase variables
- GNU Wget manual: Proxies
- Python 3.14 docs: urllib.request
- CPython 3.14.7 source: Lib/urllib/request.py (proxy_bypass by platform)
- Requests v2.34.0 release notes
- Requests v2.34.2 source: utils.py (should_bypass_proxies)
- Requests PR #7586: honor ports in IPv4 no_proxy entries
- httpx2 changelog (v2.13.1)
- httpx2 PR #1165: support IP CIDR ranges in NO_PROXY
- aiohttp docs: proxy support and trust_env
- aiohttp v3.14.3 source: helpers.py