Back to all posts
Debugging Proxy Connection Timeouts with tcpdump and Wireshark

Debugging Proxy Connection Timeouts with tcpdump and Wireshark

October 23, 2026

Why Proxy Timeouts Are Hard to Diagnose

A proxy timeout rarely tells you where the failure happened. Your scraper sees a socket timeout, but the problem could live in your local network, the proxy provider’s exit node, the upstream origin, or even a DNS resolver inside the proxy’s network. Because the proxy sits in the middle, standard application logs often show only the final symptom: ConnectTimeout or ReadTimeout.

To fix it, you need packet-level visibility. Tools like tcpdump and Wireshark let you see the actual TCP handshake, TLS negotiation, and data flow. This guide walks through a repeatable method for diagnosing proxy connection timeouts, with examples for Python scrapers and commands you can run on Linux or macOS.

What You Need Before You Start

  • A machine with tcpdump installed (Linux) or available via Wireshark (macOS/Windows).
  • Shell access to the machine running your scraper or bot.
  • The proxy endpoint, port, and credentials you are debugging.
  • A reproducible test case: a single URL that consistently times out through the proxy.

If you are using a residential or ISP proxy, remember that exit IPs rotate. Pin the capture to one proxy session or IP so you do not mix traffic from different nodes.

Step 1: Reproduce the Timeout with a Minimal Client

Start with the smallest possible client that fails. Remove retries, concurrency, and custom headers so the capture is easy to read.

Here is a minimal Python script using requests:

import requests

PROXY = "http://user:pass@GATEWAY_HOST:HTTP_PORT"
TARGET = "https://example.com"

try:
    resp = requests.get(
        TARGET,
        proxies={"http": PROXY, "https": PROXY},
        timeout=(10, 10),
    )
    print(resp.status_code, resp.elapsed.total_seconds())
except requests.exceptions.ProxyError as e:
    print("ProxyError:", e)
except requests.exceptions.ConnectTimeout as e:
    print("ConnectTimeout:", e)
except requests.exceptions.ReadTimeout as e:
    print("ReadTimeout:", e)

Run this until you reproduce the timeout. Note the exact timestamp. If it works locally but fails through the proxy, the issue is likely between your machine and the proxy, or between the proxy and the target.

Step 2: Capture Traffic with tcpdump

Run tcpdump on the interface your traffic uses. If you are unsure, ip route get <target-ip> shows the outgoing interface.

sudo tcpdump -i any -n -s 0 -w proxy-timeout.pcap port 443 or port 10000

Flags explained:

  • -i any: capture on all interfaces.
  • -n: do not resolve hostnames; keeps IP addresses and ports readable.
  • -s 0: capture full packet payload, not just headers.
  • -w proxy-timeout.pcap: write to a file for Wireshark analysis.
  • port 443 or port 10000: capture HTTPS traffic and your proxy port. Adjust the port to match your proxy configuration.

Start the capture, run your Python script, wait for the timeout, then stop tcpdump with Ctrl+C.

If you are on macOS and tcpdump requires elevated privileges, run it with sudo and enter your password.

Step 3: Filter and Inspect the Capture

Open proxy-timeout.pcap in Wireshark. Use display filters to isolate the conversation.

ip.addr == <proxy-ip> && ip.addr == <target-ip>
tcp.analysis.flags
tcp.analysis.retransmission

Look for these patterns:

  1. SYN sent, no SYN-ACK: The client reaches the proxy or origin, but the other side never acknowledges. This points to a firewall, dropped packet, or dead proxy node.
  2. SYN, SYN-ACK, then silence: The TCP handshake completes, but the application never sends data. This often means a TLS handshake stall or an application-level hang at the proxy.
  3. TLS Client Hello, no Server Hello: The proxy connected to the origin, but TLS negotiation failed. Check SNI, ALPN, or certificate validation settings.
  4. Data sent, duplicate ACKs, retransmissions: Network congestion or packet loss between the proxy and the origin.

For quick command-line inspection, tshark is useful:

tshark -r proxy-timeout.pcap -Y "tcp.analysis.retransmission" -T fields -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport

This lists retransmitted packets, which usually indicate an unhealthy path.

Step 4: Correlate Proxy Logs with Packet Captures

Packet captures show what happened on the wire, but proxy logs explain why the provider dropped or delayed the request. Match the timestamp from Step 1 with your proxy provider’s dashboard or logs.

Common log entries to check:

  • 407 Proxy Authentication Required: Your credentials are wrong or expired. The timeout may actually be authentication retries.
  • 502 Bad Gateway or 504 Gateway Timeout: The proxy could not reach the origin.
  • 429 Too Many Requests: You are hitting the proxy provider’s rate limit, not the target site.
  • connection_pool_exhausted: All sticky sessions for that IP are in use.

If the capture shows a successful TCP handshake to the proxy but no response, and the proxy logs show 504, the failure is between the proxy and the target. If the capture shows no SYN-ACK from the proxy, the failure is between your machine and the proxy.

Step 5: Common Patterns and Fixes

Proxy-to-origin TCP timeout

When the proxy connects to your machine but stalls before reaching the origin, try a different proxy location or protocol. Residential proxies sometimes throttle long-lived connections to non-browser targets.

Fix: Switch from a sticky session to a rotating IP, or reduce the request rate to that specific geo.

DNS resolution delay at the proxy

Some proxies resolve DNS on their side. If the proxy’s resolver is slow, your client sees a connect timeout even though the network is fine.

Fix: Use the target’s IP address directly if possible, or switch to a proxy provider with faster DNS in that region.

TLS handshake failure

Modern origins expect specific SNI and ALPN values. If your proxy strips or alters them, the origin drops the connection.

Fix: Verify your HTTP client sends the correct Host header and does not disable SNI. In Python, requests handles this automatically, but custom urllib3 pool managers sometimes do not.

Exhausted proxy session pool

Sticky sessions bind you to one IP for a set duration. If you open more concurrent connections than the session allows, new requests queue and time out.

Fix: Lower concurrency, increase the sticky session duration, or rotate sessions more aggressively.

Step 6: Automate Timeout Detection in CI

Do not wait for production scraping jobs to fail. Add a synthetic probe to your CI pipeline that runs the minimal client against a known URL through each proxy region you use.

Example GitHub Actions step:

- name: Proxy smoke test
  run: |
    python scripts/proxy_smoke_test.py \
      --proxy http://user:pass@GATEWAY_HOST:HTTP_PORT \
      --target https://example.com \
      --timeout 15

If the script exits non-zero, fail the job and attach the pcap file as an artifact. Over time, this builds a baseline of normal latency per region and flags degradation early.

Checklist: Before You Escalate to Your Proxy Provider

  • Reproduced the timeout with a single-request script.
  • Captured packets with tcpdump during the failure.
  • Confirmed the TCP handshake reaches the proxy.
  • Checked provider logs for 502, 504, 429, or auth errors.
  • Tested the same target without the proxy to rule out origin-side blocking.
  • Tried a different proxy location or rotation mode.

Conclusion

Proxy timeouts are frustrating because they hide the failure point behind an intermediary. By combining a minimal reproducible client, tcpdump packet captures, Wireshark filters, and provider logs, you can isolate whether the problem is local network, proxy-to-origin, or application-layer. Use the checklist above before opening a support ticket, and attach a pcap file so your provider’s engineering team can see the exact packets instead of guessing from your error message.