localhost:5173 / https-localhost

https://localhost:5173 does not load

Unless server.https is set, the Vite dev server on port 5173 speaks plain HTTP only, so a browser that opens https://localhost:5173 sends a TLS handshake to an HTTP server and fails with ERR_SSL_PROTOCOL_ERROR — use http://localhost:5173 or enable TLS.

error
This site can’t provide a secure connection
localhost sent an invalid response.
ERR_SSL_PROTOCOL_ERROR

Why does https://localhost:5173 fail when the server is running?

Without server.https, Vite creates the server with Node’s node:http module — there is no TLS layer on the port at all. The browser opens the connection with a TLS ClientHello, the HTTP server reads that as a malformed request and answers with plain text starting with "HTTP/". The browser expected a TLS record and aborts. Nothing reaches your application; the dev server is fine.

bash — vite 8.3.4, default config
$ curl https://localhost:5173/
curl: (35) LibreSSL/3.3.6: error:1404B42E:SSL routines:ST_CONNECT:tlsv1 alert protocol version

$ openssl s_client -connect localhost:5173 -msg
<<< Not TLS data or unknown version
    48 54 54 50 2f          # "HTTP/" — the server answered in plain HTTP
…:wrong version number

$ curl -s -o /dev/null -w "%{http_code}\n" http://localhost:5173/
200

Each browser names the same mismatch differently

Tested in Chrome 154 against a running dev server on 9 October 2026. The message depends on the client, the cause does not.

  • Chrome and other Chromium browsers: ERR_SSL_PROTOCOL_ERROR, "localhost sent an invalid response".
  • curl with LibreSSL (macOS): exit code 35, "tlsv1 alert protocol version".
  • curl or openssl with OpenSSL: "wrong version number".

The Local line tells you which scheme to use

Vite builds the printed URLs from one condition: if server.https is set, the scheme is https, otherwise http. The Local line is therefore the authority on which address works. If it says http://, every https:// link, bookmark or redirect to 5173 will fail the way shown above.

bash
# default
  ➜  Local:   http://localhost:5173/

# with server.https or @vitejs/plugin-basic-ssl
  ➜  Local:   https://localhost:5173/

The reverse case: http:// on a server that expects TLS

Once server.https is set, the port only accepts TLS. A plain http://localhost:5173 request is not rejected with a status code — the connection is closed without any bytes. Chrome shows ERR_EMPTY_RESPONSE ("localhost didn’t send any data"), curl exits with code 52. This usually happens after a teammate enabled TLS in the shared config and an old bookmark, proxy target or test URL still says http.

bash — server.https set
$ curl http://localhost:5173/
curl: (52) Empty reply from server

A certificate warning is a different, later failure

If the browser shows NET::ERR_CERT_AUTHORITY_INVALID instead, the TLS handshake worked — the server does speak HTTPS, the browser just does not trust who signed the certificate. That is the expected result with @vitejs/plugin-basic-ssl. In the local test its certificate listed localhost, ::1, 127.0.0.1 and fe80::1 as names, so a LAN address reached via --host is not covered and adds a name mismatch on top.

bash
$ openssl s_client -connect localhost:5173 | openssl x509 -noout -ext subjectAltName
X509v3 Subject Alternative Name:
    DNS:localhost, DNS:[::1], IP Address:127.0.0.1, IP Address:FE80:0:0:0:0:0:0:1

HTTPS with a proxy is HTTP/2 since Vite 7.2

Up to Vite 7.1, setting server.proxy together with server.https made the dev server fall back to an HTTP/1.1 HTTPS server. Since 7.2.0 it stays on HTTP/2 with HTTP/1.1 allowed as fallback, proxy or not. Older answers that say "proxy disables HTTP/2" describe that earlier behaviour. On 8.3.4 with a proxy configured, curl negotiated HTTP/2.

bash — vite 8.3.4, server.https + server.proxy
$ curl -sk -o /dev/null -w "%{http_version}\n" https://localhost:5173/
2

# faq

Questions

Why does https://localhost:5173 show ERR_SSL_PROTOCOL_ERROR?

The dev server runs without server.https and only speaks plain HTTP. The browser’s TLS handshake gets an HTTP reply and is aborted. Open http://localhost:5173 instead.

Does the Vite dev server use HTTPS by default?

No. It uses plain HTTP unless server.https is set or a plugin such as @vitejs/plugin-basic-ssl sets it. The Local line shows which scheme is active.

Why does http://localhost:5173 return ERR_EMPTY_RESPONSE?

server.https is set, so the port only accepts TLS. A plain HTTP request is closed without a response. Use https://localhost:5173.

Is ERR_CERT_AUTHORITY_INVALID the same problem?

No. That error means TLS works but the certificate is self-signed or from an untrusted CA. A locally trusted CA such as mkcert removes the warning.

Does server.proxy turn off HTTP/2 on HTTPS?

Only up to Vite 7.1. Since 7.2.0 the dev server stays on HTTP/2 with a proxy configured.

# next

Related