# Comodín, punto inicial y CIDR en NO_PROXY: una matriz probada

Source: https://ipvolt.com/es/blog/no-proxy-matching-tested
Markdown: https://ipvolt.com/es/blog/no-proxy-matching-tested.md
Language: es

[Inicio de ipvolt](https://ipvolt.com/es.md) / [Blog](https://ipvolt.com/es/blog.md) / Comodín, punto inicial y CIDR en NO_PROXY: una matriz probada

Análisis
Publicado: 2026-09-24
Actualizado: 2026-09-24
Por ipvolt
21 min de lectura

¿Qué entradas de NO_PROXY significan lo mismo en curl, Python, Node, Go y wget? Una prueba en loopback de *, puntos iniciales, CIDR, IPv6 y puertos, con datos en bruto.

NO_PROXY no tiene una gramática estándar, y los clientes que la leen discrepan en casi todo. En la matriz principal de un laboratorio en loopback ejecutado el 23 de septiembre de 2026, 15 clientes recibieron valores idénticos de `no_proxy` y `NO_PROXY`: dos builds de curl, wget, Go, cinco clientes de Python y seis configuraciones de Node.js. De las 49 combinaciones de valor y petición de la matriz principal, 21 se enrutaron igual en todos los clientes y 28 no. Cada celda está en el [results.csv](https://ipvolt.com/downloads/no-proxy-matching-tested/results.csv) publicado, una fila por cliente y petición.

Si un solo valor tiene que servir para todos, usa únicamente las formas que se comportaron de manera idéntica en todas partes y da el mismo valor a los dos nombres de variable:

```sh
# 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"
```

- El par `example.com,.example.com` (probado como `example.test,.example.test`) fue la única escritura que cubrió un dominio y todos sus subdominios en los 15 clientes. Nunca coincidió con `notexample.test`.
- Una dirección IPv4 exacta coincidió solo consigo misma en todos los clientes. Un rango CIDR IPv4 funcionó solo en 4 de los 15.
- `localhost,127.0.0.1` evitó el proxy para `127.0.0.1` y `localhost` en todos los clientes. Sin entradas de loopback, solo Go se saltó el proxy para loopback.
- wget solo lee `no_proxy`. El `net/http` de Go 1.27.1 prefiere `NO_PROXY` cuando ambas están definidas, y está previsto que Go 1.28 prefiera `no_proxy`. Mantén los dos nombres idénticos.

El conjunto de datos publicado prueba estas entradas en casos separados. En una ejecución puntual de la línea exacta de arriba, con `example.test` en lugar de `example.com`, cada una de sus nueve peticiones de prueba también se enrutó igual en los 15 clientes.

Dos tipos de escritura dan problemas. Algunas rompen un cliente o desactivan una lista. Una entrada IPv6 entre corchetes hace que httpx y httpx2 fallen al crear el cliente, y lo mismo ocurre con una entrada CIDR IPv6 en httpx 0.28.1. Un `no_proxy` en minúsculas vacío junto a un `NO_PROXY` definido desactivó la lista en 9 clientes. Otras son ignoradas en silencio por algunos clientes: `*.example.com` por 8, `*` dentro de una lista por 9, un rango CIDR IPv4 por 11, un punto final por 11, una lista separada por espacios por 9, y una entrada `host:port` por entre 4 y 6, según su forma. Incluso un `*` solo es ignorado por wget.

Estos resultados son sintéticos. Proceden de un solo Mac, un proxy en 127.0.0.1, nombres `.test` reservados y direcciones IP de documentación, y describen cómo eligen una ruta las versiones fijadas de los clientes, no cómo se comporta ningún servicio de proxy. Para saber cómo lee cada cliente las variables de proxy en primer lugar, consulta [cómo leen los clientes HTTP_PROXY y NO_PROXY](/es/guides/proxy-environment-variables). Si el `fetch()` de Node ignora el proxy por completo, empieza por [Corregir «TypeError: fetch failed» de Node.js detrás de un proxy](/es/guides/fix-node-fetch-failed-proxy).

## El subconjunto portable y las escrituras que evitar

Las tablas usan los nombres que solicitó el laboratorio: `example.test`, `sub.example.test`, `a.b.example.test` y `notexample.test`. Ningún cliente de aquí resuelve un nombre de host antes de decidir: su código fuente compara los nombres como texto, y curl, Go y Requests analizan una dirección IP presente en la URL para las comprobaciones CIDR. Ninguna de las 662 peticiones enviadas por proxy provocó una denegación registrada del sandbox por una consulta DNS o una conexión, aunque el registro del kernel descarta algunas líneas de denegación. Por tanto, los nombres de dominio reales deberían comportarse como estos.

Los 15 clientes, cada uno leyendo las variables de proxy del entorno con la configuración indicada, fueron:

- curl 8.7.1 (macOS) y curl 8.22.0;
- GNU Wget 1.25.0;
- `net/http` de Go 1.27.1 con `http.ProxyFromEnvironment`;
- `urllib` de Python 3.14.7, requests 2.34.2, httpx 0.28.1, httpx2 2.13.1 y aiohttp 3.14.3 con `trust_env=True`;
- `fetch()` y `http.get()` integrados de Node.js 26.10.0 y 24.21.0, cada uno con `NODE_USE_ENV_PROXY=1` (llamados «Node 26 fetch», «Node 26 http», etc. más abajo);
- `fetch()` de undici 7.29.1 y 8.11.0 de npm con `dispatcher: new EnvHttpProxyAgent()`, ambos en Node 26.10.0.

Estas entradas dieron el mismo resultado en los 15 clientes para las peticiones indicadas:

| Entrada | Resultado en todos los clientes |
|---|---|
| `example.test` | Evitó el proxy para `example.test`; `notexample.test` siguió usando el proxy (los subdominios difirieron en el cliente `http` de Node) |
| `.example.test` | Evitó el proxy para `sub.example.test` y `a.b.example.test` (el apex difirió en 4 clientes) |
| `example.test,.example.test` | Evitó el proxy para el apex y ambos subdominios; `notexample.test` siguió usando el proxy |
| `192.0.2.10` | Evitó el proxy para esa dirección; `192.0.2.11` siguió usando el proxy |
| `EXAMPLE.TEST`, o una petición a `EXAMPLE.TEST` | Las mayúsculas y minúsculas no cambiaron nada |
| `other.test , example.test` | Un espacio después de una coma no cambió nada |
| `other.test,,example.test` u `other.test,,` | Los elementos vacíos no coincidieron con nada |
| `localhost,127.0.0.1,::1` | Evitó el proxy para `127.0.0.1` y `localhost` (`[::1]` difirió; ver la sección sobre loopback) |
| `no_proxy` definida, `NO_PROXY` sin definir | Todos los clientes leyeron la variable en minúsculas |

Cada escritura que evitar de la respuesta anterior tiene su propia sección más abajo, con los clientes que divergieron.

## Comodín en NO_PROXY: ¿`*.example.com` coincide con `example.com`?

Depende del cliente, y 8 de 15 no lo trataron como comodín en absoluto. Con `NO_PROXY=*.example.test`:

| Petición | Evitaron el proxy | Usaron el proxy |
|---|---|---|
| `example.test` | Node 26 fetch, Node 24 fetch, undici 7.29.1 | Los otros 12 |
| `sub.example.test`, `a.b.example.test` | Go, fetch y http de Node 26 y 24, undici 7.29.1 y 8.11.0 | curl (ambos), wget, urllib, requests, httpx, httpx2, aiohttp |
| `notexample.test` | Ninguno | Los 15 |

curl, wget y los cinco clientes de Python no coincidieron con nada con esta entrada. Go, el cliente `http` de Node y undici 8.11.0 la leyeron como «solo subdominios», y el `fetch()` integrado de Node y undici 7.29.1 también evitaron el proxy para el apex.

La discrepancia sobre el apex entre el `fetch()` integrado de Node 26 y undici 8.11.0 de npm es nueva. El [PR #5777 de undici](https://github.com/nodejs/undici/pull/5777), publicado en [undici 8.11.0](https://github.com/nodejs/undici/releases/tag/v8.11.0) el 22 de septiembre de 2026, dice que una entrada `*.domain` «solo debe coincidir con `sub.example.com` / `a.b.example.com`, no con el apex». Node 26.10.0 todavía [incluye undici 8.10.2](https://github.com/nodejs/node/blob/v26.10.0/deps/undici/src/package.json). Así que, en el mismo runtime Node 26.10.0, el `fetch()` integrado evitó el proxy para `example.test` y undici 8.11.0 de npm lo envió al proxy. El mismo pull request hizo que `*` funcionara dentro de una lista o con espacios alrededor, lo que explica las únicas otras filas en las que esos dos clientes difirieron.

Para los subdominios en todos los clientes, escribe `.example.com`. Añade `example.com` si el apex también debe evitar el proxy. Ninguna escritura probada mantuvo el apex en el proxy en los 15 clientes mientras sus subdominios lo evitaban.

## Punto inicial frente a dominio sin punto: `.example.com`, `example.com` y subdominios

| Entrada y petición | Evitaron el proxy | Usaron el proxy |
|---|---|---|
| `example.test`, petición a `sub.example.test` | 13 clientes | Node 26 http, Node 24 http |
| `.example.test`, petición a `example.test` | 11 clientes | wget, Go, httpx, httpx2 |

Un dominio sin punto coincidió con sus subdominios en todas partes salvo en el cliente `http` integrado de Node, que coincidió con `example.test` de forma exacta. El laboratorio reprodujo [node#65616](https://github.com/nodejs/node/issues/65616), notificado por primera vez en Node 24.18.1, en 26.10.0 y 24.21.0. La propia [lista de formatos de NO_PROXY](https://nodejs.org/docs/v26.10.0/api/http.html#no_proxy-format) de Node llama a `example.com` «coincidencia exacta del nombre de host», lo que describe a `http.request()`, no a `fetch()`. Una corrección, [node#65617](https://github.com/nodejs/node/pull/65617), seguía abierta el 23 de septiembre de 2026.

Un punto inicial coincidió con todos los subdominios en todos los clientes, pero wget, Go, httpx y httpx2 no lo aplicaron al apex. Go lo documenta: un nombre de dominio con punto inicial «coincide solo con subdominios» ([httpproxy](https://pkg.go.dev/golang.org/x/net/http/httpproxy#Config)).

Ninguna de las dos entradas coincidió con `notexample.test` en ningún cliente. Requests solo aplica ese límite de etiqueta desde la 2.34.0; sus [notas de la versión](https://github.com/psf/requests/releases/tag/v2.34.0) dicen que «ya no realiza coincidencias voraces en los dominios de no_proxy». No se probaron versiones anteriores de Requests.

## `NO_PROXY=*` y `*` dentro de una lista

| Valor | Evitaron el proxy | Usaron el proxy |
|---|---|---|
| `*` | 14 clientes | wget |
| `other.test,*` o `" * "` | Go, httpx, httpx2, Node 26 http, Node 24 http, undici 8.11.0 | curl (ambos), wget, urllib, requests, aiohttp, Node 26 fetch, Node 24 fetch, undici 7.29.1 |

`*` funciona como valor completo, sin espacios, en todos los clientes salvo wget. curl lo documenta así: «El único comodín disponible es un solo carácter `*`» ([CURLOPT_NOPROXY](https://curl.se/libcurl/c/CURLOPT_NOPROXY.html)). wget 1.25.0 no tiene comodín. Para que un comando wget concreto no pase por el proxy, usa su opción `--no-proxy` ([manual de wget](https://www.gnu.org/software/wget/manual/wget.html#Proxies)).

## CIDR, rangos de IP y subredes en NO_PROXY

Con `NO_PROXY=192.0.2.0/24`, una petición a `192.0.2.10` evitó el proxy en curl 8.7.1, curl 8.22.0, Go y requests. Los otros 11 la enviaron al proxy: wget, urllib, httpx, httpx2, aiohttp y los seis clientes de Node. `198.51.100.10`, fuera del rango, usó el proxy en todos los clientes. Ningún cliente lanzó un error por el rango IPv4; los 11 sin soporte lo ignoraron.

- curl añadió soporte de CIDR en la 7.86.0 ([changelog](https://curl.se/changes.html)).
- Requests comprueba CIDR en [su propio comparador](https://github.com/psf/requests/blob/v2.34.2/src/requests/utils.py) antes de recurrir a urllib, y por eso los dos clientes de Python difieren.
- httpx y httpx2 aceptaron la entrada sin hacer coincidir el rango. El [PR #1165 de httpx2](https://github.com/pydantic/httpx2/pull/1165), que añadiría rangos CIDR, estaba abierto el 23 de septiembre.
- La [lista de formatos de NO_PROXY](https://nodejs.org/docs/v26.10.0/api/http.html#no_proxy-format) de Node documenta un rango con guion como `192.168.1.1-192.168.1.100` en lugar de CIDR. El laboratorio no probó rangos con guion. Un [comentario en node#57872](https://github.com/nodejs/node/issues/57872#issuecomment-5495669370) informa de que un rango con guion funcionó en `node:http` pero no en `fetch()` en una versión preliminar de la v27.

Para mantener una subred fuera del proxy en un stack mixto:

- Enumera las direcciones exactas a las que llaman tus clientes. Las direcciones IPv4 exactas fueron la única forma que coincidió en los 15.
- Un rango IPv4 puede añadirse junto a ellas para curl, Go y Requests. Con `192.0.2.10,192.0.2.0/24`, una ejecución puntual fuera del conjunto de datos publicado evitó el proxy para `192.0.2.10` en los 15 clientes y para `192.0.2.11` solo en esos 4; ningún cliente lanzó un error. Deja fuera los rangos IPv6, porque httpx 0.28.1 falla con ellos (ver más abajo).
- Un rango se aplica solo a una dirección IP escrita en la URL. curl, Go y Requests no resuelven primero un nombre de host, así que `192.0.2.0/24` no cubre un nombre que se resuelva dentro de él. Esto procede de su código fuente; el laboratorio usó únicamente direcciones IP.

## IPv6 en NO_PROXY: sin corchetes, entre corchetes y CIDR

Para una petición a `http://[2001:db8::10]/`:

| Entrada | Evitaron el proxy | No lo evitaron |
|---|---|---|
| `2001:db8::10` | 12 clientes | urllib, Node 24 fetch y undici 7.29.1 usaron el proxy |
| `[2001:db8::10]` | urllib, Node 26 fetch, Node 24 fetch, undici 7.29.1, undici 8.11.0 | 8 usaron el proxy; httpx y httpx2 lanzaron un error |
| `2001:db8::/48` | curl 8.22.0, Go | 12 usaron el proxy; httpx lanzó un error |
| `[2001:db8::10]:8080`, petición al puerto 8080 | Go, urllib, Node 26 fetch, Node 24 fetch, undici 7.29.1, undici 8.11.0 | 7 usaron el proxy; httpx y httpx2 lanzaron un error |

La forma sin corchetes fue la que mejor funcionó: coincidió en 12 clientes y no rompió ninguno. curl la pide así: «Introduce las direcciones IPv6 numéricas en la lista de nombres de host sin corchetes» ([CURLOPT_NOPROXY](https://curl.se/libcurl/c/CURLOPT_NOPROXY.html)). undici añadió la coincidencia de IPv6 sin corchetes en la 8.10.0 ([PR #5623](https://github.com/nodejs/undici/pull/5623)); undici 7.29.1, que Node 24.21.0 incluye, no la tiene.

De las dos builds de curl, solo la 8.22.0 hizo coincidir el rango IPv6. Antes de la 8.18.0 ([curl#19828](https://github.com/curl/curl/pull/19828)), el comparador de curl trataba un host como IPv6 solo cuando llegaba entre corchetes, cosa que nunca ocurre, así que una entrada CIDR IPv6 no podía coincidir.

### `InvalidURL: Invalid port` de httpx por una entrada IPv6 entre corchetes

En httpx 0.28.1 y httpx2 2.13.1, una entrada entre corchetes es peor que ignorada. Crear un cliente con el manejo del entorno por defecto lanzó `InvalidURL: Invalid port: 'db8::10]'` antes de enviar ninguna petición. Con `NO_PROXY=localhost,127.0.0.1,[::1]`, el error fue `Invalid port: ':1]'`, y las peticiones a `127.0.0.1` y `localhost` también fallaron, porque el cliente nunca llegó a crearse. httpx 0.28.1 lanzó el mismo error para `2001:db8::/48` (`Invalid port: 'db8::'`). httpx2 2.5.0 eliminó ese fallo («Allow IPv6 CIDR notation in `no_proxy`», [changelog](https://github.com/pydantic/httpx2/blob/v2.13.1/src/httpx2/CHANGELOG.md)), pero, como muestra la tabla, siguió sin hacer coincidir el rango.

Para corregirlo, escribe las entradas IPv6 sin corchetes, como `::1` o `2001:db8::10`; ambos clientes se crearon con normalidad con esas formas. Mantén los rangos IPv6 fuera de cualquier valor que lea httpx 0.28.1. Si no puedes cambiar la variable, crea ese cliente con `trust_env=False`, que también se creó con normalidad, y pásale el proxy en el código, como hace la [guía de proxy para HTTPX](/es/guides/httpx-async-proxy). Ese cliente ignora entonces todas las variables de proxy.

## Puertos en NO_PROXY: `host:port`

Para una petición al puerto 8080 indicado en la entrada:

| Entrada | Evitaron el proxy | Usaron el proxy |
|---|---|---|
| `example.test:8080` | 11 clientes | curl (ambos), wget, aiohttp |
| `192.0.2.10:8080` | 10 clientes | curl (ambos), wget, requests, aiohttp |
| `.example.test:8080` | 9 clientes | curl (ambos), wget, aiohttp, Node 26 http, Node 24 http |

En el puerto 80, las tres entradas usaron el proxy en todos los clientes, así que ningún cliente aplicó una entrada con puerto a un puerto distinto. El fallo fue el contrario: algunos clientes nunca hicieron coincidir la entrada. La documentación de curl no describe ninguna sintaxis de puerto para las entradas, y wget compara solo el nombre de host. aiohttp pasa el host sin su puerto al comparador de urllib ([código fuente](https://github.com/aio-libs/aiohttp/blob/v3.14.3/aiohttp/helpers.py)). Requests nunca hizo coincidir una entrada IPv4 que incluyera un puerto: con `192.0.2.10:8080`, usó el proxy tanto en el puerto 8080 como en el 80. Su comprobación de IPv4 compara solo el host, según el [PR #7586](https://github.com/psf/requests/pull/7586), una corrección que seguía abierta el 23 de septiembre.

Mantén los puertos fuera de un valor compartido. Si un puerto debe evitar el proxy, configura esa exclusión en el cliente que la necesita.

## Espacios, elementos vacíos, puntos finales y mayúsculas

- **Espacio antes de una coma:** con `example.test ,other.test`, wget conservó el espacio final como parte de la entrada y envió `example.test` al proxy. Los otros 14 evitaron el proxy.
- **Espacios en lugar de comas:** con `other.test example.test`, curl 8.7.1, Node 26 fetch, Node 24 fetch, undici 7.29.1 y undici 8.11.0 evitaron el proxy para ambos hosts. curl 8.22.0 lo evitó solo para `other.test`. Los otros 9 no lo evitaron para ninguno. curl 8.9.0 introdujo el cambio: «noproxy: patterns need to be comma separated» ([changelog](https://curl.se/changes.html)).
- **Elementos vacíos:** `other.test,,` no evitó el proxy para `example.test` en ningún cliente, así que ningún cliente trató un elemento vacío como «coincide con todo».
- **Puntos finales:** una entrada `example.test.`, o una petición a `http://example.test./`, coincidió solo en curl 8.7.1, curl 8.22.0, Node 26 fetch y undici 8.11.0. undici lo añadió en la 8.10.1 ([PR #5637](https://github.com/nodejs/undici/pull/5637)), así que Node 24 fetch y undici 7.29.1 no lo tienen.
- **Mayúsculas:** las entradas y los hosts en mayúsculas coincidieron en los 15 clientes.

## `NO_PROXY` frente a `no_proxy`: cuál gana y la trampa de la variable vacía

Para una petición a `example.test`:

| Entorno | Evitaron el proxy | Usaron el proxy |
|---|---|---|
| Solo `NO_PROXY=example.test` | 14 clientes | wget |
| Solo `no_proxy=example.test` | Los 15 | Ninguno |
| `NO_PROXY=example.test`, `no_proxy=other.test` | Go 1.27.1 | Los otros 14 |
| `NO_PROXY=example.test`, `no_proxy=""` | curl (ambos), 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 |

Cuando los dos nombres discrepan, el `net/http` de Go 1.27.1 usa `NO_PROXY` y los otros 14 usan `no_proxy`. Una variable en minúsculas vacía divide a los clientes 6 a 9. curl, Go, requests y el cliente `http` de Node la tratan como no definida y recurren a `NO_PROXY`. Los otros nueve la tratan como una lista vacía. [node#66202](https://github.com/nodejs/node/issues/66202), abierto el 22 de septiembre de 2026 contra una build preliminar, describe esta división entre `fetch()` y `http.request()`. El laboratorio la reprodujo en las versiones publicadas Node 26.10.0 y 24.21.0.

La precedencia de Go está cambiando. El [commit a02ddfa7ea](https://github.com/golang/net/commit/a02ddfa7eacb4cf63a5bea6b23761244a6df69f6) de golang.org/x/net, hecho para [golang/go#79656](https://github.com/golang/go/issues/79656) y publicado en x/net v0.58.0, hace que el paquete `httpproxy` prefiera los nombres en minúsculas, y el [borrador de las notas de la versión Go 1.28](https://github.com/golang/go/blob/1c3a1bac8b14c866d70b330e0229e5555670f577/doc/next/6-stdlib/99-minor/net/http/79656.md) recoge el mismo cambio para `ProxyFromEnvironment`. En una comprobación aparte, x/net v0.58.0 y v0.59.0 ya seguían `no_proxy` en el caso de conflicto. Go sigue omitiendo los valores vacíos, así que sus resultados con la variable vacía no cambian.

La variable del proxy tiene la misma trampa. Con `http_proxy=""` y `HTTP_PROXY` definida, solo Go, Node 26 http y Node 24 http usaron el proxy; los otros 12 fueron directos. curl lee `http_proxy` solo en minúsculas.

Da el mismo valor a los dos nombres, y elimina una variable con `unset` en lugar de exportarla vacía.

## localhost, 127.0.0.1 y ::1: solo Go se salta el proxy por su cuenta

Sin ningún NO_PROXY, Go fue directo para `127.0.0.1`, `localhost` y `[::1]`. Su [paquete httpproxy](https://pkg.go.dev/golang.org/x/net/http/httpproxy#Config.ProxyFunc) documenta que localhost y las direcciones de loopback nunca usan un proxy. Los otros 14 clientes enviaron las tres al proxy. Con un proxy remoto configurado, esos clientes enviarían por tanto a ese proxy una petición destinada a un servidor de desarrollo local, a menos que loopback esté en la lista.

| Valor | `127.0.0.1` y `localhost` | `[::1]` |
|---|---|---|
| `localhost,127.0.0.1,::1` | Evitado en los 15 (Go: regla de loopback integrada) | Evitado en 12 (Go: regla de loopback integrada); urllib, Node 24 fetch y undici 7.29.1 usaron el proxy |
| `localhost,127.0.0.1,[::1]` | httpx y httpx2 lanzaron un error; 13 lo evitaron (Go: regla de loopback integrada) | Evitado en urllib, Node 26 fetch, Node 24 fetch, undici 7.29.1 y 8.11.0, y en Go por su regla de loopback integrada; httpx y httpx2 lanzaron un error; 7 usaron el proxy |

Las exclusiones de Go en esta tabla proceden de su regla integrada, no de la lista, así que no demuestran que `[::1]` funcione como entrada en Go; en la matriz principal, Go usó el proxy para la entrada entre corchetes `[2001:db8::10]`.

Incluye `localhost,127.0.0.1`. Añade un `::1` sin corchetes si usas loopback IPv6, y nunca `[::1]`.

## ¿HTTPS a través de CONNECT recibe la misma decisión de exclusión?

Sí, en esta ejecución. Para cada una de las 8 URL HTTPS, todos los clientes tomaron la misma decisión que para la URL HTTP correspondiente: 120 de 120 comparaciones. Todas las peticiones HTTPS enviadas por proxy llegaron al proxy como `CONNECT`.

## Node.js: NO_PROXY no funciona con fetch ni con http.request

Cuatro cosas distintas pueden hacer que NO_PROXY parezca roto en Node. El caso del `ProxyAgent` explícito procede de la documentación de undici y no se probó; los otros tres son resultados del laboratorio.

**La activación.** Sin `NODE_USE_ENV_PROXY=1` ni `--use-env-proxy` ([documentación](https://nodejs.org/docs/v26.10.0/api/cli.html#node_use_env_proxy1)), `fetch()` y `http.get()` de Node 26 y 24 ignoraron las variables de proxy y fueron directos en las 36 celdas de control. La [guía sobre fetch de Node](/es/guides/fix-node-fetch-failed-proxy) cubre ese fallo.

**Un `ProxyAgent` explícito.** La documentación de undici describe un `ProxyAgent` como algo que enruta todas las peticiones a través de su proxy y no menciona ninguna lista de exclusión; leer `no_proxy` y `NO_PROXY` es lo que añade `EnvHttpProxyAgent` (documentación de undici 8.11.0 de [ProxyAgent](https://github.com/nodejs/undici/blob/v8.11.0/docs/docs/api/ProxyAgent.md) y [EnvHttpProxyAgent](https://github.com/nodejs/undici/blob/v8.11.0/docs/docs/api/EnvHttpProxyAgent.md)). El código que pasa un `ProxyAgent` como `dispatcher`, como hace la [guía de configuración de proxy para fetch de Node.js](/es/guides/nodejs-fetch-proxy), ignora por tanto NO_PROXY. Para conservar una lista de exclusión, usa `new EnvHttpProxyAgent()`, que lee las variables o acepta las opciones `httpProxy`, `httpsProxy` y `noProxy`.

**Dos comparadores en el mismo runtime.** `http.request()` usa el comparador propio de Node, y el `fetch()` integrado usa el `EnvHttpProxyAgent` de undici. Discreparon en 20 de las 72 filas no base en Node 26.10.0 y en 19 de 72 en Node 24.21.0. El comparador de Node lleva el comentario `TODO(joyeecheung): share code with undici.` ([código fuente](https://github.com/nodejs/node/blob/v26.10.0/lib/internal/http.js)), y compartir ese código sigue siendo un punto abierto en el issue de seguimiento [node#57872](https://github.com/nodejs/node/issues/57872).

**undici incluido frente a undici de npm.** En Node 26.10.0, el `fetch()` integrado (undici 8.10.2) y undici 8.11.0 de npm difirieron en 4 filas, todas casos de comodín. El `fetch()` de Node 24.21.0 y undici 7.29.1 de npm no difirieron en absoluto. undici 7.29.1 y 8.11.0 difirieron en 11 filas.

La tabla siguiente muestra una fila por cada tipo de diferencia en Node 26.10.0, con los valores de las secciones anteriores. Las otras 12 de las 20 filas discrepantes repiten estos tipos para otros hosts y peticiones, más el caso `http_proxy=""`.

| Diferencia | fetch | http | undici 8.11.0 |
|---|---|---|---|
| Dominio sin punto, petición a un subdominio | Evitado | Proxy | Evitado |
| `*.example.test`, petición al apex | Evitado | Proxy | Proxy |
| `*` dentro de una lista | Proxy | Evitado | Evitado |
| Dirección IPv6 entre corchetes | Evitado | Proxy | Evitado |
| Punto inicial con un puerto | Evitado | Proxy | Evitado |
| Entrada con punto final | Evitado | Proxy | Evitado |
| Espacios en lugar de comas | Evitado | Proxy | Evitado |
| `no_proxy` vacío, `NO_PROXY` definido | Proxy | Evitado | Proxy |

Node 24.21.0 mostró el mismo patrón, con dos excepciones. Para el punto final, sus dos clientes usaron el proxy. Para una entrada IPv6 sin corchetes, solo `http` evitó el proxy.

Un [comentario del 1 de septiembre de 2026 en node#57872](https://github.com/nodejs/node/issues/57872#issuecomment-5495669370) ya comparó `node:http` con `fetch()` en una build preliminar de la v27.0.0. Las filas de Node del laboratorio coinciden con las 8 filas de esa tabla que pudo comparar.

## Lo que GitLab encontró en 2021 y lo que cambió

El [artículo de 2021 de Stan Hu](https://about.gitlab.com/blog/we-need-to-talk-no-proxy/) en GitLab, con investigación de Nourdin el Bacha, comparó curl, wget, Ruby, Python, Go y Java a partir de su código fuente y su documentación. Recomendó un mínimo común denominador y propuso un estándar.

De las 32 celdas de su tabla de no_proxy que este laboratorio pudo comprobar (8 filas para curl, wget, Python mediante urllib y Go), 31 siguen coincidiendo. La excepción es curl y CIDR: la tabla de 2021 dice que no, pero ambas builds de curl lo respetaron aquí. La celda de precedencia «Uppercase» de Go sigue coincidiendo con Go 1.27.1 y está previsto que cambie en Go 1.28. El laboratorio no pudo comprobar las filas «Supports regexes?» y «Resolves IP addresses?»; la segunda marca Go como «Yes», pero el propio texto del artículo dice que solo Ruby resuelve nombres de host, y el código fuente de Go 1.27.1 no lo hace. Ruby y Java no se probaron.

Su consejo del mínimo común denominador se sostiene solo en parte. Un `no_proxy` solo en minúsculas, las comas y las direcciones IPv4 exactas funcionaron en los 15 clientes; un punto inicial siguió sin cubrir el apex en 4, como advertía el artículo, y solo 4 respetaron CIDR IPv4, así que evitar CIDR sigue siendo sensato. «Los sufijos siempre coinciden» falló en el cliente `http` de Node, los «valores hostname:port separados por comas» coincidieron solo en entre 9 y 11 clientes por entrada (8 coincidieron con las tres), y ninguna forma de IPv6 dio el mismo resultado en todos los clientes.

Varios de estos comportamientos son recientes. Requests 2.34.0 (11 de mayo de 2026) añadió el límite de etiqueta. httpx2 2.5.0 (25 de junio de 2026) dejó de fallar con las entradas CIDR IPv6, sin hacerlas coincidir. undici 8.10.0, 8.10.1 y 8.11.0 (agosto y septiembre de 2026) añadieron IPv6 sin corchetes, los puntos finales y las nuevas reglas de comodín.

## Cómo funciona la prueba y cómo repetirla

Un pequeño proxy HTTP en 127.0.0.1 registró cada petición en forma absoluta y cada `CONNECT`, la respondió por sí mismo y no reenvió nada. Cada petición se ejecutó en su propio proceso bajo `sandbox-exec` de macOS, con un perfil que deniega todo el tráfico saliente salvo loopback, de modo que un intento directo fallaba en la máquina y no llegaba a ningún host real. Una celda cuenta como enviada por proxy solo cuando el proxy registró su petición; que el cliente recibiera o no una respuesta nunca decidió nada. Sin ningún NO_PROXY definido, los 15 clientes enviaron por proxy todas las formas de URL.

La ejecución publicada, el 23 de septiembre de 2026 de 19:13 a 19:15 UTC, tiene 1.266 celdas. Una repetición limpia que siguió los pasos de abajo a partir del archivo publicado clasificó las 1.266 celdas de forma idéntica.

Para leer la matriz publicada sin ejecutar nada, extrae el archivo y ejecuta `python3 no_proxy_lab.py table results.json`. No necesita configuración ni red, e imprimió la misma salida en Python 3.9.6 que en 3.14.7. Una repetición completa necesita macOS, Python 3.14 y Go, unos 700 MB de disco y acceso a nodejs.org, pypi.org y registry.npmjs.org durante `setup`, que no instala nada a nivel del sistema:

```sh
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 main
```

`compare` sale con 0 solo cuando todas las celdas tienen la misma clasificación. El [README](https://ipvolt.com/downloads/no-proxy-matching-tested/README.md) explica su salida con otras builds de clientes, cómo probar otras versiones o tu propio valor de NO_PROXY, el modo `--isolation none` para otros sistemas y todos los campos de `results.json`.

Descargas:

- [no-proxy-matching-tested.zip](https://ipvolt.com/downloads/no-proxy-matching-tested/no-proxy-matching-tested.zip): todos los archivos de abajo, con `clients/` en su sitio (recréalo si descargas los archivos uno a uno)
- [README.md](https://ipvolt.com/downloads/no-proxy-matching-tested/README.md): método, requisitos, comandos y cómo leer los resultados
- [results.json](https://ipvolt.com/downloads/no-proxy-matching-tested/results.json) y [results.csv](https://ipvolt.com/downloads/no-proxy-matching-tested/results.csv): todas las celdas de la ejecución publicada
- [no_proxy_lab.py](https://ipvolt.com/downloads/no-proxy-matching-tested/no_proxy_lab.py), [clients/py_client.py](https://ipvolt.com/downloads/no-proxy-matching-tested/clients/py_client.py), [clients/node_client.cjs](https://ipvolt.com/downloads/no-proxy-matching-tested/clients/node_client.cjs), [clients/go_client.go](https://ipvolt.com/downloads/no-proxy-matching-tested/clients/go_client.go) y [nonet.sb](https://ipvolt.com/downloads/no-proxy-matching-tested/nonet.sb): el harness, los clientes de una sola petición y el perfil de sandbox solo loopback
- [requirements.txt](https://ipvolt.com/downloads/no-proxy-matching-tested/requirements.txt), [package.json](https://ipvolt.com/downloads/no-proxy-matching-tested/package.json) y [package-lock.json](https://ipvolt.com/downloads/no-proxy-matching-tested/package-lock.json): las versiones exactas fijadas de Python y npm

## Límites

- Una sola máquina macOS 15.7.4 arm64, una sola fecha y las versiones indicadas arriba. Cualquier versión nueva puede cambiar una fila: Node 26.10.0 todavía no incluye undici 8.11.0, y está previsto que Go 1.28 cambie la fila de las variables en conflicto.
- Linux no se probó. Cada cliente compara NO_PROXY en su propio código o en la biblioteca estándar de su lenguaje, y con las variables de proxy definidas, el urllib de Python sigue la [misma ruta de entorno](https://github.com/python/cpython/blob/v3.14.7/Lib/urllib/request.py) en macOS que en Linux. Por tanto, en Linux las filas deberían depender de la versión del cliente y no del sistema operativo. Es una inferencia a partir del código fuente, no un resultado en Linux; el README da ejemplos.
- La matriz probó solo el manejo de las variables de entorno, con la configuración indicada arriba, y solo el proxy de reenvío HTTP. No probó opciones de proxy explícitas, otros agentes o dispatchers, la configuración de proxy del sistema, Windows, SOCKS, archivos PAC, redirecciones ni autenticación de proxy. Para una respuesta 407, consulta [cómo corregir el error de proxy 407](/es/guides/fix-proxy-error-407).
- No se probaron los rangos con guion, las direcciones parciales como `192.168.*`, las entradas que dependen de la resolución DNS, ni Ruby, Java, .NET, Deno y Bun; el README enumera el resto.
- Las dos comprobaciones puntuales de arriba se ejecutaron el 24 de septiembre de 2026 con el mismo harness y los mismos clientes. No están en `results.json`; el README muestra cómo repetirlas.

ipvolt ejecutó estas comprobaciones en local el 23 y el 24 de septiembre de 2026 con las versiones de cliente indicadas arriba. No se probó ningún proveedor externo, servicio de proxy ni red, y nada de lo aquí expuesto describe el servicio de ipvolt.

Si quieres enterarte cuando se abra el acceso a ipvolt, [únete a la lista de acceso anticipado](https://ipvolt.com/#waitlist-closing). Un correo cuando se abra el acceso. Nada más.

## Fuentes

- [GitLab (2021): We need to talk: Can we standardize NO_PROXY?](https://about.gitlab.com/blog/we-need-to-talk-no-proxy/)
- [nodejs/node#57872: node:http vs fetch() NO_PROXY table (comment, 2026-09-01)](https://github.com/nodejs/node/issues/57872#issuecomment-5495669370)
- [nodejs/node#65616: NO_PROXY=example.com and http.request() subdomains](https://github.com/nodejs/node/issues/65616)
- [nodejs/node#65617: http: match subdomains for plain NO_PROXY entries](https://github.com/nodejs/node/pull/65617)
- [nodejs/node#66202: fetch() and http.request() with an empty lowercase variable](https://github.com/nodejs/node/issues/66202)
- [Node.js 26.10.0 docs: NO_PROXY format](https://nodejs.org/docs/v26.10.0/api/http.html#no_proxy-format)
- [Node.js 26.10.0 docs: NODE_USE_ENV_PROXY](https://nodejs.org/docs/v26.10.0/api/cli.html#node_use_env_proxy1)
- [Node.js 26.10.0 source: lib/internal/http.js (http.request matcher)](https://github.com/nodejs/node/blob/v26.10.0/lib/internal/http.js)
- [Node.js 26.10.0: bundled undici version](https://github.com/nodejs/node/blob/v26.10.0/deps/undici/src/package.json)
- [undici PR #5777: NO_PROXY wildcard semantics](https://github.com/nodejs/undici/pull/5777)
- [undici v8.11.0 release notes](https://github.com/nodejs/undici/releases/tag/v8.11.0)
- [undici PR #5623: match bare IPv6 addresses in no_proxy](https://github.com/nodejs/undici/pull/5623)
- [undici PR #5637: ignore trailing dots when matching no_proxy](https://github.com/nodejs/undici/pull/5637)
- [undici v8.11.0 docs: ProxyAgent](https://github.com/nodejs/undici/blob/v8.11.0/docs/docs/api/ProxyAgent.md)
- [undici v8.11.0 docs: EnvHttpProxyAgent](https://github.com/nodejs/undici/blob/v8.11.0/docs/docs/api/EnvHttpProxyAgent.md)
- [libcurl: CURLOPT_NOPROXY](https://curl.se/libcurl/c/CURLOPT_NOPROXY.html)
- [curl changelog](https://curl.se/changes.html)
- [curl#19828: IPv6 CIDR notation in NO_PROXY (fixed in 8.18.0)](https://github.com/curl/curl/pull/19828)
- [Go: golang.org/x/net/http/httpproxy Config](https://pkg.go.dev/golang.org/x/net/http/httpproxy#Config)
- [Go: httpproxy Config.ProxyFunc (localhost and loopback)](https://pkg.go.dev/golang.org/x/net/http/httpproxy#Config.ProxyFunc)
- [golang.org/x/net commit a02ddfa7ea: httpproxy prefers lowercase proxy variables (x/net v0.58.0)](https://github.com/golang/net/commit/a02ddfa7eacb4cf63a5bea6b23761244a6df69f6)
- [golang/go#79656: inconsistent HTTP_PROXY precedence (milestone Go 1.28)](https://github.com/golang/go/issues/79656)
- [Go 1.28 release-note draft: ProxyFromEnvironment prefers lowercase variables](https://github.com/golang/go/blob/1c3a1bac8b14c866d70b330e0229e5555670f577/doc/next/6-stdlib/99-minor/net/http/79656.md)
- [GNU Wget manual: Proxies](https://www.gnu.org/software/wget/manual/wget.html#Proxies)
- [Python 3.14 docs: urllib.request](https://docs.python.org/3.14/library/urllib.request.html)
- [CPython 3.14.7 source: Lib/urllib/request.py (proxy_bypass by platform)](https://github.com/python/cpython/blob/v3.14.7/Lib/urllib/request.py)
- [Requests v2.34.0 release notes](https://github.com/psf/requests/releases/tag/v2.34.0)
- [Requests v2.34.2 source: utils.py (should_bypass_proxies)](https://github.com/psf/requests/blob/v2.34.2/src/requests/utils.py)
- [Requests PR #7586: honor ports in IPv4 no_proxy entries](https://github.com/psf/requests/pull/7586)
- [httpx2 changelog (v2.13.1)](https://github.com/pydantic/httpx2/blob/v2.13.1/src/httpx2/CHANGELOG.md)
- [httpx2 PR #1165: support IP CIDR ranges in NO_PROXY](https://github.com/pydantic/httpx2/pull/1165)
- [aiohttp docs: proxy support and trust_env](https://docs.aiohttp.org/en/stable/client_advanced.html#proxy-support)
- [aiohttp v3.14.3 source: helpers.py](https://github.com/aio-libs/aiohttp/blob/v3.14.3/aiohttp/helpers.py)

## Entérate cuando se abra el acceso a ipvolt.

Ya que estás aquí

ipvolt está en desarrollo. Deja tu correo y te avisaremos una sola vez cuando se abra el acceso.

Un correo cuando se abra el acceso. Nada más.

[Solicitar acceso anticipado](https://ipvolt.com/es/blog/no-proxy-matching-tested#waitlist-blog-end)

[Privacidad](https://ipvolt.com/privacy)


## Artículos relacionados

- [Configurar proxies en MostLogin: añadir, probar y compartir](https://ipvolt.com/es/blog/mostlogin-proxy-setup.md) (Análisis, 17 sept 2026, 9 min de lectura): Añade un proxy a los perfiles de MostLogin paso a paso: protocolo, host y puerto, credenciales, comprobación de IP, acceso del equipo, importación masiva y errores.
- [Precios en Amazon: tu oferta frente a la Oferta Destacada](https://ipvolt.com/es/blog/amazon-offer-vs-featured-offer.md) (Análisis, 16 sept 2026, 7 min de lectura): Compara tu oferta de Amazon con la Oferta Destacada usando contexto emparejado, envío conocido y un modelo offline probado que conserva los datos ausentes.
- [Actualizaciones de listings en Amazon: aceptado no es activo](https://ipvolt.com/es/blog/amazon-listing-update-reconciliation.md) (Análisis, 14 sept 2026, 9 min de lectura): Diagnostica actualizaciones de listings de Amazon aceptadas separando atributos enviados, ofertas activas, inventario y comprabilidad, con una matriz de conciliación.

## Guías relacionadas

- [Variables de entorno de proxy: HTTP_PROXY y NO_PROXY](https://ipvolt.com/es/guides/proxy-environment-variables.md): Diagnostica las diferencias de enrutamiento de HTTP_PROXY, HTTPS_PROXY, ALL_PROXY y NO_PROXY en curl, Python Requests y Node.js con una comprobación local aislada.
- [Corregir TypeError: fetch failed de Node.js detrás de un proxy](https://ipvolt.com/es/guides/fix-node-fetch-failed-proxy.md): Descifra TypeError: fetch failed de Node.js tras un proxy: imprime la cadena err.cause, corrige un HTTPS_PROXY ignorado o el desfase de undici y lee un 403, 407 o 502.
- [Usar un proxy con curl: -x, variables de entorno, SOCKS5 y auth](https://ipvolt.com/es/guides/curl-proxy-setup.md): Cómo usar un proxy con curl: la opción -x, las variables http_proxy y https_proxy, SOCKS5 con socks5h, autenticación del proxy y cómo leer los errores CONNECT y 407.

## Sobre ipvolt

Análisis técnico del equipo de ipvolt.

El acceso a ipvolt aún no está abierto.

[Leer el original en inglés](https://ipvolt.com/blog/no-proxy-matching-tested.md)
