---
title: "¿Qué es un proxy MITM? Guía de Charles, Fiddler y mitmproxy"
description: "Un proxy MITM pasa tu propio tráfico por una herramienta local para leer solicitudes y respuestas HTTPS. Comparamos Charles, Fiddler y mitmproxy para depurar."
url: https://proxynet.io/es/blog/mitm-proxy
date: 2026-09-24
author: "Acar Diveroli"
category: "Proxy 101, Tutoriales"
lang: es
---

# ¿Qué es un proxy MITM? Guía de Charles, Fiddler y mitmproxy

Tu scraper recibe un `403` en una página de categoría que en el navegador se abre sin problemas, y el error no dice nada más allá del código de estado. Si pusieras lado a lado la solicitud del navegador y la de Python, verías la diferencia en un minuto, pero HTTPS mantiene las dos selladas. Un proxy MITM en tu propio equipo abre ese sello solo para ti.

Esta guía explica cómo lee HTTPS un proxy MITM, compara Charles, Fiddler y mitmproxy con sus condiciones de licencia de 2026 y trata el certificado raíz, tus propias apps móviles, una configuración de Python probada y el encadenamiento con un proxy upstream. Todo parte de tu propio dispositivo y tu propia app, o de un sistema que tengas permiso por escrito para probar.

> **Nota: Respuesta breve**
>
> Un proxy MITM es una herramienta de depuración que se sitúa entre tu navegador, script o app e internet, en tu propio equipo. Para leer HTTPS, crea sobre la marcha un certificado para cada sitio y lo firma con un certificado raíz local que genera en su primera ejecución. Ese certificado raíz solo debe estar en tu dispositivo de pruebas, y solo durante la prueba. Charles es una app de escritorio de pago, Fiddler Everywhere funciona por suscripción, Fiddler Classic tiene desde el 3 de agosto de 2026 una licencia solo para uso no comercial, y mitmproxy es de código abierto y se programa en Python.

## ¿Qué es un proxy MITM?

«Man-in-the-middle» (intermediario) es el nombre de un ataque: alguien se cuela entre dos partes sin que lo sepan y lee lo que se envían. Un proxy MITM usa esa misma posición para depurar. Tú instalas la herramienta, el tráfico es tuyo y eres tú quien confía en su certificado, así que nadie resulta engañado. Las empresas usan la técnica para la inspección TLS en los equipos de su personal; ese lado corresponde a [proxy o firewall](/es/blog/proxy-vs-firewall).

Un forward proxy normal ([cómo funciona un servidor proxy](/es/blog/what-is-a-proxy-server)) solo ve el host de destino de una solicitud HTTPS, por la línea `CONNECT example.com:443`, y después transporta bytes cifrados. Un proxy MITM termina la conexión cifrada en tu máquina, así que ve la URL completa, cada cabecera y el cuerpo.

## ¿Cómo abre un proxy MITM el tráfico HTTPS?

[RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-connect) describe un túnel como un relé ciego que pasa los mensajes sin modificarlos. Un proxy normal respeta esa regla después de `CONNECT`; un proxy MITM la rompe a propósito, para los clientes que confían en su certificado. Según [la descripción del flujo de mitmproxy](https://docs.mitmproxy.org/stable/concepts/how-mitmproxy-works/):

1. El cliente envía `CONNECT example.com:443` a la herramienta local.
2. La herramienta responde `200 Connection Established`, como si hubiera abierto el túnel.
3. El cliente inicia el handshake TLS e indica el host en el campo SNI.
4. La herramienta se conecta a ese host por TLS y lee los nombres (CN y SAN) del certificado del servidor.
5. Crea un certificado con esos nombres y lo firma con su certificado raíz local (la CA, autoridad de certificación).
6. Si el cliente confía en esa CA, el handshake se completa y la herramienta lee el tráfico en texto plano antes de volver a cifrarlo hacia el servidor.

Si el cliente no confía en la CA, el paso 6 falla con un error de certificado, como debe ser. Un gateway de Proxynet nunca hace el paso 5: retransmite el túnel `CONNECT` a ciegas, así que con los [Proxies HTTPS](https://proxynet.io/es/https-proxy) no necesitas ningún certificado raíz en tu dispositivo.

## Charles, Fiddler y mitmproxy comparados

Según las páginas de los propios fabricantes en septiembre de 2026; solo modelos de licencia, sin precios.

| Herramienta | Licencia | Plataformas | Interfaz | Puerto por defecto | Proxy upstream | Automatización |
|---|---|---|---|---|---|---|
| Charles | Licencia de usuario de pago tras 30 días de prueba | Windows, macOS, Linux | App de escritorio | Normalmente 8888 | HTTP, HTTPS y SOCKS; autenticación Basic o NTLM | Breakpoints, Rewrite, Map Local |
| Fiddler Everywhere | Suscripción, 10 días de prueba | Windows, macOS, Linux | App de escritorio | 8866 | Cadena de proxy manual; autenticación Kerberos, Negotiate o NTLM | Rules |
| Fiddler Classic | Solo uso no comercial desde el 3 de agosto de 2026 | Solo Windows | App de escritorio | 8888 | No se trata aquí | FiddlerScript |
| mitmproxy | Código abierto, MIT | Windows, macOS, Linux | Terminal, navegador (`mitmweb`), línea de comandos (`mitmdump`) | 8080 | `--mode upstream:` con `upstream_auth` (Basic) | Addons de Python, CI |

Charles y Fiddler Everywhere encajan con los equipos de QA móvil que editan solicitudes en una ventana; mitmproxy encaja con los desarrolladores que quieren la comprobación dentro de una suite de pruebas o en CI, donde cada paso es una función de Python. Burp Suite está orientado a las pruebas de seguridad, que quedan fuera de esta guía.

## ¿Qué es Charles Proxy y cuándo elegirlo?

Charles es una app de escritorio que puedes probar durante 30 días antes de comprar una licencia de usuario. Solo descifra los hosts de su lista [SSL Proxying](https://www.charlesproxy.com/documentation/proxying/ssl-proxying/) (`*` significa todos los hosts) y reenvía el resto del tráfico HTTPS sin abrirlo. Un tester apunta el proxy Wi-Fi del iPhone al portátil y al puerto 8888, permite el dispositivo cuando Charles lo pregunta y después usa Breakpoints para editar solicitudes, Map Local para responder desde un archivo y la limitación de ancho de banda (throttling) para imitar una red lenta.

## ¿Qué es Fiddler? Classic y Everywhere

**Fiddler Classic** solo funciona en Windows, ya no se desarrolla y tiene FiddlerScript. Desde el 3 de agosto de 2026 su licencia solo permite el uso no comercial; los usuarios comerciales tuvieron hasta el 17 de septiembre de 2026 para migrar, y [no existe una licencia de pago de Classic](https://www.telerik.com/fiddler/fiddler-classic/commercial-use).

**Fiddler Everywhere** es el producto comercial: Windows, macOS y Linux, una suscripción tras 10 días de prueba, compatibilidad con HTTP/2 y TLS 1.3, y el puerto 8866. Activas la captura HTTPS, confías en su certificado raíz y filtras las sesiones por host.

## ¿Qué es mitmproxy? Tres interfaces y addons de Python

mitmproxy tiene licencia MIT; la versión 12.2.3 (12 de mayo de 2026) necesita Python 3.12 o posterior. Incluye `mitmproxy` (vista de terminal), `mitmweb` (vista en el navegador) y `mitmdump` (sin interfaz, para scripts y CI), todos en el puerto 8080 por defecto.

En el primer arranque [crea su CA](https://docs.mitmproxy.org/stable/concepts/certificates/) en `~/.mitmproxy`, única para esa instalación: la clave privada (`mitmproxy-ca.pem`) está junto a los archivos de certificado de cada plataforma (`mitmproxy-ca-cert.pem`, `.p12`, `.cer`). Con el proxy configurado en un dispositivo, `mitm.it` ofrece el archivo adecuado y los pasos de instalación. Un addon es un archivo de Python cuyas funciones llevan el nombre de eventos como `response`.

## ¿Por qué necesitas un certificado raíz y es seguro?

Quien tiene la clave privada de una CA puede crear un certificado que parece válido para cualquier sitio en todos los dispositivos que confían en ella. El riesgo está en esa clave, no en la herramienta:

- **Solo una CA generada por tu propia herramienta.** Nuestra [guía sobre la seguridad de los proxies gratis](/es/blog/are-free-proxies-safe) dice que no instales un certificado que te pida un servicio de proxy, y eso sigue en pie: una CA remota permite que un desconocido lea tu tráfico. Una herramienta en tu propio equipo es distinta, porque su clave nunca sale de tu máquina.
- **Solo en dispositivos de prueba, solo durante la prueba.** No compartas `~/.mitmproxy` ni lo subas a un repositorio, y elimina la CA al terminar.
- **Mantén activas las comprobaciones de la herramienta.** La opción `ssl_insecure` de mitmproxy omite las comprobaciones de certificado hacia el servidor, y su texto de ayuda advierte que eso deja al propio mitmproxy expuesto a una interceptación.

Para eliminar la CA:

- **Windows:** `certmgr.msc` > Entidades de certificación raíz de confianza > Certificados.
- **macOS:** borra el certificado de la herramienta en Acceso a Llaveros.
- **iPhone:** Ajustes > General > VPN y gestión de dispositivos > el perfil > Eliminar perfil.
- **Android (Pixel):** Ajustes > Seguridad y privacidad > Más ajustes de seguridad > Cifrado y credenciales > Credenciales de usuario; en otras marcas cambian los pasos anteriores a los dos últimos.

## Ver el tráfico de tu propia app móvil en Android y iPhone

Apunta el proxy Wi-Fi del teléfono a la dirección IP de tu equipo y al puerto de la herramienta, con los [ajustes de proxy de Android](/es/blog/android-proxy-settings) o los [ajustes de proxy del iPhone](/es/blog/iphone-proxy).

**Android.** Según la documentación de [configuración de seguridad de red](https://developer.android.com/privacy-and-security/security-config), las apps orientadas a Android 7.0 (nivel de API 24) o posterior solo confían por defecto en las CA del sistema, así que tu app puede fallar con un error TLS mientras el navegador funciona. En tu propia app, añade un bloque `debug-overrides`:

```xml
<!-- res/xml/network_security_config.xml -->
<network-security-config>
    <debug-overrides>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
    </debug-overrides>
</network-security-config>
```

Haz referencia a él con `android:networkSecurityConfig="@xml/network_security_config"` en el manifiesto. Android ignora el bloque cuando `android:debuggable` es false, así que una build de release mantiene las reglas de confianza normales.

**iPhone.** Después de instalar el perfil, activa la confianza total en [Ajustes > General > Información > Ajustes de confianza de certificados](https://support.apple.com/en-us/102390).

**Pinning.** Una app que fija certificados (certificate pinning) rechaza el certificado de la herramienta. En tu propia app, ajusta el pinning en la build de pruebas; en la app de otra persona, el pinning es decisión del desarrollador, y esta guía se detiene ahí.

## Interceptar, editar y repetir solicitudes

Las tres herramientas te permiten pausar una solicitud y cambiar una cabecera antes de que salga, responder a una solicitud con un archivo local para probar una pantalla de error y volver a enviar una solicitud guardada, de modo que un fallo que aparece una vez al día se pueda repetir cuando quieras. En mitmproxy, `-w flows.mitm` guarda los flujos y `-C flows.mitm` los repite. Repite solicitudes solo contra tu propia API o contra un endpoint que tengas permiso para probar, dentro de sus límites de velocidad.

Para la solicitud en segundo plano de una página web basta con DevTools ([encontrar la solicitud XHR](/es/blog/static-vs-dynamic-pages)); la herramienta local es para scripts y apps.

## Depurar un scraper de Python con un proxy MITM

Volvamos al `403`: pasamos el script por `mitmdump`, registramos cada respuesta e imprimimos los detalles de la solicitud en cada error. Probado con Python 3.13, mitmproxy 12.2.3 y Requests 2.34.2 (`pip install mitmproxy requests`).

El addon, `debug_addon.py`, imprime una línea por respuesta y, en los `4xx` y `5xx`, las cabeceras que suelen diferir de las de un navegador, si se envió una cookie y el principio del cuerpo:

```python
"""Addon de mitmdump: una línea por respuesta, detalles de la solicitud en cada 4xx y 5xx."""
from mitmproxy import http

WATCH = ("User-Agent", "Accept", "Accept-Language", "Accept-Encoding")

def response(flow: http.HTTPFlow) -> None:
    req, resp = flow.request, flow.response
    print(f"{resp.status_code} {req.method} {req.pretty_url}")
    if resp.status_code < 400:
        return
    for name in WATCH:
        print(f"    {name}: {req.headers.get(name, '(not sent)')}")
    print(f"    Cookie: {'sent' if 'Cookie' in req.headers else 'not sent'}")
    body = resp.get_content(strict=False) or b""  # descomprimido si es gzip o br
    print(f"    body: {body[:300].decode('utf-8', 'replace')!r}")
```

El script, `scraper_debug.py`, solo usa el proxy cuando `DEBUG_PROXY` está definida y confía en la CA local mediante `verify`. La documentación de Requests advierte que [`verify=False` deja la aplicación expuesta a ataques MitM](https://requests.readthedocs.io/en/latest/user/advanced/), así que aquí no aparece nunca:

```python
"""Descarga páginas con Requests; define DEBUG_PROXY para pasarlas por un mitmdump local."""
import os
import sys
from pathlib import Path

import requests

DEBUG_PROXY = os.environ.get("DEBUG_PROXY")  # p. ej. http://127.0.0.1:8080
MITM_CA = Path.home() / ".mitmproxy" / "mitmproxy-ca-cert.pem"

session = requests.Session()
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
    "Accept-Language": "en-GB,en;q=0.9",
})

def request_options():
    options = {"timeout": (5, 30)}  # (conexión, lectura) en segundos
    if DEBUG_PROXY:
        if not MITM_CA.is_file():
            sys.exit(f"{MITM_CA} not found: start mitmdump once, it creates the CA there.")
        # Se pasa en cada solicitud: HTTPS_PROXY puede sobrescribir un valor de Session.proxies.
        options["proxies"] = {"http": DEBUG_PROXY, "https": DEBUG_PROXY}
        options["verify"] = str(MITM_CA)  # confía en la CA local, nunca verify=False
    return options

def fetch(url):
    try:
        return session.get(url, **request_options())
    except requests.exceptions.SSLError as exc:
        sys.exit(f"TLS check failed for {url}: is {MITM_CA} the CA of the "
                 f"mitmdump that is running?\n{exc}")
    except requests.exceptions.ProxyError as exc:
        sys.exit(f"Debug proxy {DEBUG_PROXY} did not answer: is mitmdump running?\n{exc}")

if __name__ == "__main__":
    for url in sys.argv[1:] or ["https://httpbin.org/headers"]:
        resp = fetch(url)
        print(resp.status_code, url)
        for name, value in resp.request.headers.items():
            print(f"    {name}: {value}")
```

Arranca `mitmdump` solo en la dirección de loopback:

```bash
mitmdump --listen-host 127.0.0.1 -p 8080 -s debug_addon.py -w flows.mitm
```

Después ejecuta el script en una segunda terminal (en PowerShell, define antes `$env:DEBUG_PROXY = "http://127.0.0.1:8080"`):

```bash
DEBUG_PROXY=http://127.0.0.1:8080 python scraper_debug.py https://httpbin.org/headers https://httpbin.org/status/403
```

La ventana de `mitmdump` mostró esto (sin las líneas de conexión):

```text
200 GET https://httpbin.org/headers
403 GET https://httpbin.org/status/403
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
    Accept: */*
    Accept-Language: en-GB,en;q=0.9
    Accept-Encoding: gzip, deflate, br
    Cookie: not sent
    body: ''
```

Ahora abre la página en un navegador configurado con el mismo proxy. `Accept: */*` frente al `text/html,...` del navegador, o una cookie de una página anterior que falta, son hallazgos típicos; lo segundo significa que el script se saltó un paso ([Sesiones y cookies en Python](/es/blog/python-login-session-cookies)). Si el sitio rechaza a propósito a los clientes que no son navegadores, esa es su respuesta: usa su API o pide permiso.

Un archivo de CA equivocado detuvo el script con `CERTIFICATE_VERIFY_FAILED` y nuestra pista. `mitmdump --set server=false -C flows.mitm -s debug_addon.py` repitió las dos solicitudes y terminó sin abrir ningún puerto de escucha.

El servidor ve el handshake TLS de la herramienta, no el de tu script, así que un sitio que comprueba [huellas TLS](/es/blog/tls-fingerprinting) puede responder de otra forma mientras la herramienta está activa; compara con una ejecución sin `DEBUG_PROXY`. Los reintentos ante un `429` están en [Códigos de estado HTTP en web scraping](/es/blog/http-status-codes-web-scraping), las variables de entorno en [Proxy con wget](/es/blog/wget-proxy), la rotación en [Cómo rotar proxies en Python](/es/blog/how-to-rotate-proxies-in-python) y la elección de biblioteca en [HTTPX, Requests y AIOHTTP](/es/blog/httpx-vs-requests-vs-aiohttp).

## Probar desde otro país: encadenar la herramienta local a un proxy

Para ver los precios que tu app muestra a un usuario en Alemania, envía el tráfico del dispositivo a la herramienta MITM local (donde se descifra), de ahí a un proxy upstream y después al destino. Con destinos HTTPS, el proxy upstream solo transporta el túnel ya cifrado de nuevo; Proxynet no lo descifra.

**mitmproxy.** El modo upstream reenvía cada solicitud, y `upstream_auth` añade autenticación Basic:

```bash
mitmdump --listen-host 127.0.0.1 --mode upstream:http://pr.proxynet.io:8000 --set upstream_auth=user:pass -s debug_addon.py
```

Lo probamos contra un proxy local que exige contraseña. Con una contraseña incorrecta, el script recibió un `502` de `mitmdump`, y su registro mostró la causa: el upstream rechazó el `CONNECT` con un `407`.

**Charles.** [External Proxies](https://www.charlesproxy.com/documentation/configuration/external-proxies/) admite direcciones separadas para HTTP, HTTPS y SOCKS, con autenticación Basic o NTLM y una lista de exclusiones con comodines.

**Fiddler Everywhere.** Settings > Gateway admite una cadena de proxy manual, y la documentación indica [Kerberos, Negotiate y NTLM](https://www.telerik.com/fiddler/fiddler-everywhere/documentation/installation-and-setup/advanced-installation/configuring-fiddler-alongside-proxy-auth) para la autenticación upstream, no un usuario y una contraseña. Con Proxynet, autoriza en su lugar la dirección IP de tu equipo ([user:pass y lista de IP autorizadas](/es/blog/proxy-authentication-methods)).

Usa [Proxies móviles](https://proxynet.io/es/mobile-proxy) para una IP de operador móvil o [Proxies residenciales](https://proxynet.io/es/residential-proxy) para una conexión doméstica; el escenario completo está en nuestra página de [pruebas de aplicaciones](/es/app-testing).

## ¿Para qué se usa un proxy MITM?

- **Scraper frente a navegador:** encuentra la cabecera que convierte un `200` en un `403` ([códigos de estado HTTP](/es/blog/http-status-codes-web-scraping)).
- **Postman:** ve las cabeceras finales que envía Postman ([configuración de proxy en Postman](/es/blog/postman-proxy)).
- **Tu propia app:** sigue las llamadas a la API y los errores en un teléfono de pruebas ([pruebas de aplicaciones](/es/app-testing)).
- **Cabeceras de proxy:** detecta `Via` o `X-Forwarded-For` en HTTP sin cifrar ([niveles de anonimato de un proxy](/es/blog/anonymous-proxy-levels)).
- **Un `407`:** comprueba si las credenciales llegan al proxy upstream ([métodos de autenticación de proxy](/es/blog/proxy-authentication-methods)).
- **Comprobaciones de proxy:** confirma la salida y las respuestas antes de un trabajo ([cómo probar un proxy](/es/blog/how-to-test-a-proxy)).

## Errores comunes

- **Dejar la CA instalada.** Cualquiera que consiga la clave más adelante puede hacerse pasar por cualquier sitio ante ese dispositivo.
- **Publicar código con `verify=False`.** Apunta `verify` al archivo de la CA.
- **Esperar que una app de Android confíe en una CA de usuario.** Las apps de nivel de API 24+ la ignoran fuera de una build de depuración que lo permita.
- **No añadir el host a SSL Proxying en Charles.** Ves entradas `CONNECT` cifradas y ningún contenido.
- **Escuchar en todas las interfaces.** Sin `--listen-host`, `mitmdump` se enlazó a `0.0.0.0` y `::` en nuestra prueba; enlázalo a `127.0.0.1` salvo que tenga que conectarse un teléfono.
- **Compartir archivos de flujos sin cuidado.** Contienen cookies y cabeceras.
- **Usar Fiddler Classic en el trabajo después de agosto de 2026.** Su licencia es solo para uso no comercial.

## Guía de decisión

| Necesidad | Recomendación |
|---|---|
| Comparar la solicitud de un scraper con la del navegador | mitmproxy con un addon pequeño; `verify` de Requests apuntando al archivo de la CA |
| Editar solicitudes en una ventana para QA móvil | Charles o Fiddler Everywhere |
| Fiddler para trabajo comercial en Windows | Fiddler Everywhere u otra herramienta, no Fiddler Classic |
| Tráfico HTTPS de tu propia app de Android | `debug-overrides` solo en la build de depuración |
| Probar tu app como un usuario de otro país | Encadena la herramienta local a un proxy móvil o residencial ([pruebas de aplicaciones](/es/app-testing)) |
| Encontrar la solicitud en segundo plano de una página web | La pestaña Red (Network) de DevTools; no hace falta una herramienta MITM |

## Preguntas frecuentes

### ¿Es legal usar un proxy MITM?

En tu propio dispositivo y tu propia app, o en un sistema que tengas permiso por escrito para probar, es una herramienta de depuración. Leer en secreto el tráfico de otras personas es otra cosa. Sobre el scraping, consulta [¿El web scraping es legal?](/es/blog/is-data-web-scraping-legal).

### ¿Es seguro mitmproxy?

La herramienta es de código abierto y funciona en local. El riesgo es la clave privada de la CA en `~/.mitmproxy`: mantenla en privado, instala la CA solo en dispositivos de prueba y elimínala después.

### ¿Fiddler Classic sigue siendo gratis y en qué se diferencia de Fiddler Everywhere?

Desde el 3 de agosto de 2026, Fiddler Classic solo es gratis para uso no comercial; funciona en Windows y ya no se desarrolla. Fiddler Everywhere es el producto de pago y multiplataforma, compatible con HTTP/2 y TLS 1.3.

### ¿Hay una alternativa gratis a Charles Proxy?

mitmproxy es de código abierto y funciona en las mismas plataformas; `mitmweb` le da una vista en el navegador. El propio Charles tiene una prueba de 30 días.

### He instalado el certificado en Android, ¿por qué sigue sin aparecer el tráfico de mi app?

Las apps orientadas al nivel de API 24 o posterior solo confían por defecto en las CA del sistema. Permite las CA de usuario en la build de depuración de tu propia app con `debug-overrides`, y ajusta el pinning en la build de pruebas si la app fija certificados.

### ¿Qué diferencia hay entre un proxy MITM, un proxy normal y una VPN?

Un proxy normal y una VPN transportan el tráfico cifrado sin leerlo y cambian tu IP de salida ([proxy o VPN](/es/blog/proxy-vs-vpn)). Un proxy MITM lo abre en tu equipo y mantiene tu IP, salvo que lo encadenes a un proxy upstream.

## En resumen

Un proxy MITM es una herramienta para leer tu propio tráfico, con una CA que se queda en local, es temporal y solo se instala en dispositivos de prueba. Charles y Fiddler Everywhere sirven para trabajar en una ventana; mitmproxy, para scripts y CI. Cuando una prueba tiene que salir desde otro país, encadena la herramienta local a un proxy upstream, empezando por nuestra página de [pruebas de aplicaciones](/es/app-testing).
