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.
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.
$ 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.
# 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.
$ 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.
$ 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:1HTTPS 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.
$ 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
# sources
- Vite — server.https
- Vite source — resolveHttpServer in http.ts (v8.3.4)
- Vite source — resolveServerUrls in utils.ts (v8.3.4)
- Vite changelog — 7.2.0-beta.0: support HTTP2 even if proxy feature is used (#20869)
- @vitejs/plugin-basic-ssl
Checked against the Vite documentation on 2026-10-09.