// concept

HTTP vs HTTPS in development — when does it matter?

Updated 2026-05-09

The short answer

In 2026, develop on HTTPS by default. Most browser APIs that touch user data, sensors, or persistent storage require it, and so do every OAuth provider, payment gateway, and webhook signing scheme.

The remaining cases where plain HTTP is fine: pure server-side hello-world, internal CI test harnesses, and tooling pipelines. Anything a real browser will load — switch to HTTPS.

What breaks on plain HTTP

A non-exhaustive list of features that throw or silently fail on http://localhost in 2026:

  • Service Workers — registration is HTTPS-only (with a localhost exemption that doesn't extend to LAN IPs or tunneled HTTP URLs).
  • Web Push — requires service workers, so HTTPS.
  • Geolocationnavigator.geolocation requires a "secure context".
  • Camera / MicrophonegetUserMedia requires a secure context.
  • Web Bluetooth / USB / Serial — secure context required.
  • HTTP/2 + HTTP/3 — virtually all browser implementations are HTTPS-only.
  • Cookies with the Secure flag — won't be set over HTTP.
  • SameSite=None cookies — must also be Secure; effectively HTTPS-only.
  • Mixed content — an HTTPS page loading HTTP resources is blocked.
  • CORS preflight + credentialsAccess-Control-Allow-Credentials semantics differ subtly under HTTP.

A separate category: third-party services that enforce HTTPS regardless of what the browser does:

  • OAuth providers (Apple, Google, Facebook, GitHub) — most reject HTTP redirect URIs outright.
  • Payment processors (Stripe, Plaid, Adyen) — webhook endpoints and checkout returns must be HTTPS.
  • App stores — iOS App Transport Security blocks plain HTTP traffic from the app side.

The localhost exemption

Browsers treat http://localhost (and http://127.0.0.1) as a secure context for most APIs, intentionally. This means in pure local dev, plain HTTP gets you most of the way.

The exemption breaks down when:

  • You access from another device on your LAN — http://192.168.1.42:3000 is NOT a secure context.
  • You want to test from a phone — see above.
  • A third party (OAuth provider, webhook) needs to call your URL — they don't see localhost; they see whatever public name you've given.

How to develop with real HTTPS

Three options that work in 2026:

Option 1: A tunnel service

Run an agent that gives your localhost a real, certificate-valid HTTPS URL on the public internet. ngrok, lrok, Cloudflare Tunnel are the popular ones.

$ lrok http 3000
  Forwarding https://violet-mole.lrok.io  →  http://127.0.0.1:3000

Cert is real — Let's Encrypt at the edge. Browsers, OAuth providers, and webhook senders all accept it the same way they accept your prod URL.

Option 2: mkcert + local CA

mkcert installs a local certificate authority on your machine and issues HTTPS certs for localhost / *.test / arbitrary names you pick. Real HTTPS on https://localhost:3000, no tunnel.

Tradeoff: Per-machine setup. Trust must be installed on every browser and every device that hits the URL. Mobile testing requires manually installing the CA on the phone — moderate friction.

Option 3: Caddy / Traefik with their built-in dev TLS

Caddy and Traefik both ship local-TLS modes that issue self-signed certs automatically. Same trust-on-each-device friction as mkcert.

What I'd pick

For most dev work: a tunnel service. The same URL works from your laptop, your phone (cellular, no LAN required), and external services. Single config, no per-machine cert management.

For air-gapped / offline dev: mkcert.

Walkthrough for various stacks — Next.js, Django, Rails, Go, etc.

// shipping?

lrok gives your localhost a public HTTPS URL with a reserved subdomain on the free plan. $9/mo flat for unlimited.

Related