
An HTTPS development server is useful when you need to test the same origin behavior your deployed site uses, or when a browser feature, cookie, or integration depends on an HTTPS URL. You can create a locally trusted certificate without buying one or exposing your development server to the internet.
The key is to use the exact hostname covered by the certificate and keep its local certificate authority private. This guide uses mkcert to create a certificate and shows how to configure a Vite development server. The same certificate-generation steps work with other servers that accept a certificate and private key.
Do you need HTTPS on localhost?
Many browser APIs are restricted to secure contexts, but http://localhost and loopback addresses such as 127.0.0.1 are treated as potentially trustworthy. That means a local HTTP page can use some APIs that a normal HTTP website cannot. MDN's secure-context guide explains the distinction.
Use local HTTPS when you need to test the HTTPS origin itself: redirects, scheme-sensitive integrations, secure-cookie behavior on a non-localhost development hostname, or a feature that depends on a trusted certificate. It can also help reproduce a production setup more closely. It does not make localhost accessible to a remote webhook provider; an outside service still needs a reachable test endpoint, such as a properly configured development tunnel.
An origin includes its scheme, host, and port. http://localhost:5173 and https://localhost:5173 are different origins, so switching schemes can affect cookies, storage, and cross-origin requests. Keep your local API URL, OAuth callback, and browser app on the hosts and schemes your test expects.
Install mkcert
Install mkcert using a package manager or prebuilt binary listed in its official installation guide. The documented options include Homebrew on macOS, Chocolatey or Scoop on Windows, and Linux package tools or prebuilt releases. On Linux, mkcert may need the system's certificate tools; check the current instructions for your distribution.
mkcert creates a local certificate authority (CA) and installs it into supported trust stores. Run the following once for your user account:
mkcert -install
Trust-store support differs by operating system and browser. For example, mkcert documents system stores and selected browser-specific stores, and notes that Firefox may need a restart after installation. Review the supported root stores if your browser still reports that the certificate is untrusted.
Generate a certificate for your development host
From your project directory, create a certificate for the names you will actually type into the browser:
mkcert -key-file localhost-key.pem -cert-file localhost.pem localhost 127.0.0.1 ::1
This creates one certificate that covers localhost, the IPv4 loopback address, and the IPv6 loopback address. A certificate is valid for its listed names, not every name that happens to reach your computer. If your app uses another host, add that exact name when generating the certificate. For example, app.localhost can be useful for a local subdomain; MDN lists names ending in .localhost as potentially trustworthy.
The certificate does not include a port number. You can use it on different local ports, but the browser URL must use a hostname included in the certificate. If you use a custom development domain, make sure it resolves to your computer and that your server accepts requests for it. Avoid using a real production hostname that resolves to a public service.
Keep the certificate and key out of source control. Add the generated files to your project's .gitignore:
/localhost.pem
/localhost-key.pem
The private key is not a CA key, but it still should not be published. mkcert's rootCA-key.pem is more sensitive: its project documentation warns that it can be used to intercept secure requests from your machine. Never commit or share that CA private key.
Configure a Vite development server
Vite's server.https option accepts TLS options, including the certificate and key. In a Vite config file in the project root, configure the generated files:
import { readFileSync } from 'node:fs'
import { defineConfig } from 'vite'
export default defineConfig({
server: {
https: {
key: readFileSync(new URL('./localhost-key.pem', import.meta.url)),
cert: readFileSync(new URL('./localhost.pem', import.meta.url)),
},
},
})
Start the dev server using your project's usual command, then open its HTTPS URL with the same hostname you put in the certificate, such as https://localhost:5173. If the browser shows a certificate warning, do not click through and treat the page as trusted. Check that the dev server loaded the files, the browser trusts the mkcert CA, and the URL hostname matches a name in the certificate.
For another development hostname, include it when generating the certificate and use it in the browser. Vite also has an allowedHosts setting for custom hosts; prefer an explicit host you control rather than allowing every hostname. Vite warns that allowing arbitrary hosts can expose a development server to DNS-rebinding requests.
Check the browser and related tools
In the browser's developer console, check whether the page is a secure context:
window.isSecureContext
The result should be true for a secure context. This is a useful feature check, but it does not verify every part of your production TLS setup. Also test the specific flow you care about, such as a redirect, callback, or service-worker registration. For example, our guide to building an offline-capable web app with service workers and IndexedDB explains how service workers fit into an offline workflow.
Command-line tools may use different certificate stores from your browser. The mkcert documentation notes that Node.js may not trust a locally installed CA automatically and describes using NODE_EXTRA_CA_CERTS. If a Node process makes an HTTPS request to your local server, set the variable before starting the process.
On macOS or Linux:
export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"
In PowerShell:
$env:NODE_EXTRA_CA_CERTS = "$(mkcert -CAROOT)\rootCA.pem"
Check the Node.js CLI documentation and restart the process after changing environment variables.
For a phone, another computer, or a teammate's machine, localhost refers to that device itself, not your development computer. You need a network-reachable host and a certificate that covers the name used on that device. The device must also trust the development CA. Treat CA installation as a security decision; never distribute the CA private key.
Troubleshoot common certificate problems
- The browser says the certificate is untrusted. Confirm mkcert installed its CA into a trust store the browser uses, then restart the browser. Check the project's current supported-store notes if necessary.
- The certificate name does not match. Open the same hostname listed when the certificate was generated. A certificate for
localhostdoes not automatically cover127.0.0.1or a custom domain. - The app still loads over HTTP. Confirm the dev server has HTTPS enabled and use its
https://URL. A trusted certificate does not change the server's protocol by itself. - A Node request fails while the browser works. The Node process may not use the same trust store. Follow Node's
NODE_EXTRA_CA_CERTSinstructions and restart the process. - A webhook provider cannot reach the app. Local HTTPS protects the connection to your machine; it does not make the server public. Use a controlled tunnel or a deployed test endpoint, and do not send production secrets to an unreviewed endpoint.
Remove the local CA when you no longer need it
Delete the generated leaf certificate and key from the project when they are no longer needed. To remove mkcert's local CA from trust stores, use its -uninstall option from the same user account that installed it, then check any browser-specific stores you configured separately. This does not delete the CA files: mkcert -CAROOT prints their location. If you are permanently retiring that CA, remove rootCA.pem and rootCA-key.pem from that directory after uninstalling it; keep the private key protected until you do.
What local HTTPS does not test
A locally trusted certificate is for development, not a production certificate authority. It does not validate production DNS, certificate renewal, your hosting provider's TLS configuration, CDN behavior, or the real network path to your users. Keep those checks in a staging environment or deployment test.
Local HTTPS is one part of a realistic browser setup. It can help exercise APIs that require secure contexts, including Web Crypto and passkey flows; see our guides to using the Web Crypto API in the browser and implementing passkeys with WebAuthn. Test each feature and origin on its own rather than assuming a trusted local certificate reproduces production.