Try 500 MB of US mobile proxy data free for 30 days.Start free trial
October 25, 202613 min read

HTTPS Proxy CONNECT: How the Tunnel Works and How to Debug It

Isometric illustration of a proxy tunnel

When you send an HTTPS request through an HTTP proxy, your client first sends a plain-text CONNECT host:443 request. The proxy opens a TCP connection to that host and port and answers with a 2XX status. After that it forwards raw bytes in both directions without reading them. Your TLS handshake then runs end to end with the destination site, so the proxy never sees the content.

That one handshake explains most of the confusing behavior engineers run into: why a proxy that serves plain HTTP fine rejects HTTPS, why a 407 shows up before any page loads, and why you can't read or cache HTTPS traffic at the proxy. This guide walks through the exchange, shows it in curl and Python, and lists the failure modes in the order we would check them.

TL;DR

  • CONNECT asks a proxy to open a blind TCP tunnel to a host and port. Any 2XX reply means the proxy has switched to tunnel mode.
  • TLS is negotiated between your client and the destination, not the proxy. The proxy can authenticate you and filter by host and port, but it cannot inspect the encrypted stream.
  • Most failures come from three places: proxy credentials (407), a port or host the proxy won't tunnel to (403), or a proxy that doesn't allow CONNECT at all.
  • CONNECT carries TCP only. UDP-based traffic such as HTTP/3 needs newer mechanisms.

Table of Contents

What the CONNECT method does

An ordinary HTTP proxy request names a full URL. The proxy reads it, fetches the page, and returns the response. That works because the proxy can see everything. HTTPS breaks that model, because the request is encrypted before it leaves your machine.

The fix is to ask the proxy for a pipe instead of a page. MDN describes CONNECT as a request for the proxy to establish an HTTP tunnel to a destination server and, if that succeeds, blindly forward data both ways until the tunnel closes. The request target is unusual: it holds only the host and port, separated by a colon.

Here is the whole exchange on the wire:

CONNECT example.com:443 HTTP/1.1
Host: example.com:443
Proxy-Authorization: Basic dXNlcjpwYXNz

HTTP/1.1 200 Connection established

(TLS ClientHello goes here, straight to example.com)

Three things to notice:

  1. The first message is plain text, even though the next one is encrypted. That is why the proxy can read your Proxy-Authorization header and your target host, and nothing else.
  2. The proxy's job after the 200 is only to move bytes. MDN's proxy guide frames this as using a higher-level protocol (HTTP) to carry a lower-level one (TCP).
  3. The target port is nearly always 443, but the method doesn't require it. That is a security question for the proxy operator, covered below.

Why you can't see inside the tunnel

Because the TLS handshake happens between your client and the destination, the certificate your client validates belongs to the real site. The proxy cannot decrypt, cache, or modify the stream. For scraping and data collection this is a feature: your requests reach the target exactly as your client built them, and the proxy sees only a host, a port, and byte counts.

There are proxies that do decrypt HTTPS, by terminating TLS themselves and presenting their own certificate. That is a different design, usually found in corporate inspection setups, and your client has to trust the proxy's certificate for it to work. It is not what CONNECT tunneling does.

"HTTPS proxy" can mean two different things

The phrase causes real confusion, and it is worth separating the two meanings before you debug anything.

What people sayWhat it meansWhat you configure
HTTPS through a proxyYour traffic to an HTTPS site travels over a CONNECT tunnel. The connection to the proxy itself is usually plain HTTP.A normal http://proxy:port URL
HTTPS proxy (TLS to the proxy)The connection between you and the proxy is itself wrapped in TLS, then a CONNECT runs inside it.A proxy URL starting with https://

The first is the common case, and it is the one most proxy providers mean. Your credentials in the CONNECT request travel unencrypted to the proxy in that setup, which matters on untrusted networks. The second adds a TLS layer on the first hop. For a deeper look at the trade-off, see our HTTP vs HTTPS proxy decision rules.

In both cases, the traffic to the destination is protected by the end-to-end TLS session, and the https:// scheme in the proxy URL only describes the first hop.

Making a CONNECT request in practice

With curl

The everything curl guide notes that curl treats whatever you pass to -x or --proxy as an HTTP proxy by default, and uses port 1080 if you don't give one. When the target URL is HTTPS, curl issues CONNECT on its own.

curl -v -x http://USER:[email protected]:8080 https://httpbin.org/ip

Run it with -v and read the output. You will see the CONNECT httpbin.org:443 line go out, the proxy's status line come back, and only then the TLS handshake. If the status line is anything other than 2XX, the problem is the proxy, not the website.

CONNECT request, proxy status, and TLS handshake sequence

To force a tunnel for a plain HTTP target, add --proxytunnel (-p). It is rarely needed, but it helps when you want to rule out proxy-side rewriting.

With Python requests

import requests

proxies = {
    "http": "http://USER:[email protected]:8080",
    "https": "http://USER:[email protected]:8080",
}
r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=30)
print(r.status_code, r.text)

Note that the https key names the scheme of the target URL, not the scheme of the proxy. Both entries usually point at the same http:// proxy address. Putting https:// in the proxy value tells the library to speak TLS to the proxy, which only works if the proxy listens for TLS.

In other stacks

The same pattern holds almost everywhere: you give the library a proxy URL, and it runs CONNECT whenever the target is HTTPS. Language-specific details differ mostly in where credentials go. We cover the common ones in our guides for Node.js with Axios, Java and Apache HttpClient, and C# HttpClient with SocketsHttpHandler. Some HTTP clients also document CONNECT tunneling alongside SOCKS support, as the httpx proxy plugin wiki does for Ruby.

Reading the status line: where CONNECT fails

Most debugging comes down to the response to the CONNECT. Check it before you touch your scraper code.

Response to CONNECTLikely causeFirst thing to check
200 then TLS errorTunnel works; the problem is between you and the siteCertificate, SNI, TLS version, system clock
407 Proxy Authentication RequiredMissing or wrong proxy credentialsUsername format, URL-encoded special characters, auth scheme
403 ForbiddenProxy policy blocks the host or portTarget port, allowlist, account permissions
405 or 501Proxy doesn't support or allow CONNECTProxy type and configuration
502 or 504Proxy could not reach the destinationTarget host, DNS, upstream health
Connection reset or timeout before any statusNetwork path or proxy port is wrongProxy host and port, firewalls

A useful habit: separate the layers. The proxy hop, the tunnel, and the TLS session with the destination each fail in different ways. Our proxy error troubleshooting guide goes through finding the failing layer fast.

407 on the CONNECT, not on the page

A 407 during a tunnel setup surprises people because they expect authentication to happen on the HTTPS request. It can't: that request is encrypted and the proxy can't read it. Credentials have to be presented on the plain-text CONNECT. If your client sends them only after the tunnel opens, they never reach the proxy.

Common causes include special characters in the password that aren't URL-encoded, a client that waits for a challenge it should answer preemptively, and credentials sent for the wrong proxy in a chain. Our walkthrough on fixing 407s with curl covers the auth schemes in detail.

The proxy handles GET but refuses CONNECT

This is the classic trap. Wikipedia's HTTP tunnel article is the reference for the observation that a proxy forwarding plain HTTP requests may still have tunneling disabled or restricted. If HTTP URLs work and HTTPS URLs fail with 403, 405 or 501, test the same proxy with curl -v against an HTTPS target and read the status line. Then ask the proxy's operator whether CONNECT is permitted for your account and the port you need.

Port restrictions

The method itself doesn't limit the port, so operators do. An open proxy that tunnels anywhere can be abused to relay spam over SMTP or to reach internal SSH servers, which is why MDN flags this risk and many administrators allow only specific destinations. In practice that often means port 443 only. If your tool connects to a non-standard HTTPS port and gets a 403 from the proxy, the access control list rejected it before the request left the network.

Chained proxies

CONNECT is hop-by-hop. MDN notes that a proxy forwards a CONNECT request only when another proxy sits in front of the origin, since most origin servers don't implement the method. If you chain proxies, every hop must allow CONNECT, and a failure at the second hop can look like a failure at the first. Test each hop alone with curl before combining them.

What CONNECT can't do

CONNECT tunnels TCP. It has no native way to carry UDP, which matters for QUIC and HTTP/3. Cloudflare's primer on proxies explains why HTTP-based tunneling became a standard, reusable building block, and the newer MASQUE work exists to cover what CONNECT can't. One of those standards, RFC 9484, defines how to proxy IP packets in HTTP.

For scraping and data collection this rarely bites, since the vast majority of target sites still negotiate HTTP/1.1 or HTTP/2 over TCP, and clients fall back automatically. If you need a protocol-level choice between tunneling HTTP and a general-purpose relay, see our comparison of SOCKS5 and HTTP proxies, including DNS leak tests.

What CONNECT can't do — overview diagram

Where CONNECT shows up in server and gateway setups

If you run infrastructure rather than a scraper, you will meet CONNECT from the other side. The NGINX documentation on a CONNECT forward proxy and the Envoy Gateway task on HTTP CONNECT tunnels both describe tunnels used for HTTPS traffic through a proxy. The Squid wiki on HTTPS lays out the choices a proxy has when a client requests an https:// URL: tunnel it, or intercept it. Whichever you run, keep the allowlist tight: restrict destination ports, require authentication, and log the CONNECT targets.

Our perspective: why CONNECT behavior matters for mobile proxies

We run a mobile proxy network with real US carrier IPs in 46 cities, and most support questions we see about HTTPS come back to the same few points. Almost everything a customer's client does with our proxies starts with a CONNECT. So the handshake is the first place we look, and it should be yours too.

A few habits we recommend to teams building scrapers and monitoring jobs:

  • Read the CONNECT status first. A 200 means the proxy hop is healthy. If the page then fails, the cause is on the destination side: TLS, rate limits, or the site's own defenses. A 407 means credentials, full stop.
  • Match session type to the job. Sticky sessions keep one IP for a stretch of related requests, which suits logins and multi-step flows, and rotating sessions spread independent requests across IPs. Each new tunnel is a new CONNECT, so how often your client reconnects decides how often your exit IP can change. Our notes on session management for stable proxy workflows go through this.
  • Test with curl before code. One verbose curl call against a known endpoint takes seconds and tells you whether the proxy, your credentials and your network path all work. It removes your scraper from the list of suspects.
  • Keep credentials per person or per job. Separate credentials make it easy to see who generated which traffic and to revoke one without disturbing the rest. We built credential management for teams and organizations around that idea.

The tunnel is what makes real mobile IPs usable for HTTPS targets: your client talks TLS directly to the destination, and the destination sees a carrier IP rather than a datacenter range. That is the reason we build on carrier IPs and support HTTP, HTTPS and SOCKS5 across common environments.

— Jon

A short checklist for a CONNECT that won't connect

  1. Confirm host and port. A typo here looks like a timeout or reset with no status line at all.
  2. Run curl -v through the proxy to an HTTPS URL. Find the CONNECT line and the status that follows.
  3. If 407, fix credentials. URL-encode special characters and confirm the username format your provider expects.
  4. If 403, check the target port and host. Standard 443 is the safest assumption for HTTPS.
  5. If 405 or 501, ask whether CONNECT is enabled for your account or proxy type.
  6. If 200 but TLS fails, look past the proxy. Check the clock, TLS version and certificate store on your machine.
  7. Only then debug your application code. Retries, timeouts and concurrency come last.

If you're comparing providers for a scraping or monitoring project, the features data teams should compare first is a good criteria list, and access control for teams is covered in private proxy benefits for secure team access.

Try it on real mobile IPs

If you want to run the curl test above against real US carrier IPs, Masklabs gives you HTTP, HTTPS and SOCKS5 access with sticky or rotating sessions and city-level targeting across 46 US cities. Billing is metered per byte, and you set up credentials yourself, with no sales call. Plans on the pricing page start with Starter at $30.00 per month, then Basic at $100.00, Advanced at $500.00 and Scale at $1,000.00 per month. There is also a free trial with limited data, which is plenty for a handful of CONNECT tests.

FAQ

What is an HTTP CONNECT proxy?

It is a proxy that accepts the CONNECT method and opens a TCP tunnel to the host and port you name. After the proxy replies with a 2XX status, it passes bytes between you and the destination without reading them. This is how HTTPS traffic crosses an HTTP proxy.

Can a proxy see my HTTPS traffic through a CONNECT tunnel?

Not the content. The proxy sees the destination host and port from the CONNECT line, your proxy credentials, and how much data moves. The TLS session runs between your client and the destination, so page content, headers and cookies stay encrypted. The exception is a proxy that deliberately intercepts TLS, which requires your client to trust its certificate.

Do I use http:// or https:// in the proxy URL?

Use http:// unless your provider says its proxy endpoint accepts TLS connections. The scheme describes how you talk to the proxy, not how you reach the target site. HTTPS targets work fine over an http:// proxy URL because the client issues CONNECT and then negotiates TLS with the site.

Why does my proxy return 403 or 405 on CONNECT?

A 403 usually means the proxy's policy blocks that destination host or port, and many operators allow only port 443. A 405 or 501 means the proxy doesn't support or allow the method at all. Confirm with curl -v against an HTTPS URL, then check your account's permissions with the operator.

Does CONNECT work for HTTP/3 or UDP?

No. CONNECT tunnels TCP only. Newer mechanisms such as MASQUE address UDP and IP proxying, but for typical scraping over HTTP/1.1 or HTTP/2, a standard CONNECT proxy is all you need.

Sources

Recommended