http-server
http-server is a zero-configuration-oriented command-line static file server for Node.js. Point it at a directory and it serves files, directory indexes, optional CORS headers, basic authentication, TLS, precompressed gzip or Brotli assets, and fallback proxying. It is useful for previewing a build, sharing a directory on a trusted network, or creating a simple test fixture. It is not an application framework: there are no routes, templates, sessions, request handlers, build pipeline, live reload, or automatic certificate management.
Excellent as a disposable local file server, provided you make the bind address and cache policy explicit. It is the wrong layer for a public production origin, application routes, or a live-reload development loop.
Use it if
- You need a disposable local server for a generated site, coverage report, or fixture directory
- You want one CLI that can add CORS, custom headers, basic auth, or a fallback proxy without writing Node code
- You need to test prebuilt .gz or .br assets using browser Accept-Encoding negotiation
- You want the same static preview command on any machine with Node 12 or newer
- You intend to expose it directly to the public internet: it binds to 0.0.0.0, enables directory listings, and shows auto-index pages by default
- You expect development live reload or file watching: neither appears in the documented feature set
- You need an application server with middleware or route handlers: the interface is a static-serving CLI with proxy flags, not an Express-style framework
- You want fresh cache behavior without flags: caching defaults to 3,600 seconds, and the README explicitly tells local users to pass -c-1 to disable it
- You want an official ready-made container: the README says no public Docker image is currently provided and documents building one yourself
Setup reality
npx http-server is the cleanest occasional use because it avoids a permanent global command; install it as a dev dependency when scripts and lockfile reproducibility matter. Version 14.1.1 requires Node 12 or later and pulls in a small stack for MIME lookup, proxying, authentication, port selection, colors, and HTML encoding. The defaults are more open than many developers notice: the address is 0.0.0.0, directory listings and auto-index are enabled, cache max-age is 3,600 seconds, and the server chooses ./public when that directory exists or ./ otherwise. For a private local preview, pass -a 127.0.0.1 -c-1 --no-dotfiles and specify the directory explicitly. Port 8080 is the default; -p 0 searches for an open port starting there, which is convenient interactively but awkward for tools that need a known URL. CORS mode sends Access-Control-Allow-Origin: *, so it is not a selective production policy. The SPA fallback is a documented proxy trick with a trailing question mark, not a first-class history fallback, and proxying adds node-http-proxy behavior you must test. TLS requires your own cert.pem and key.pem. Self-signed certificates still need OS or browser trust work, and an encrypted key's passphrase is read only from NODE_HTTP_SERVER_SSL_PASSPHRASE. Basic-auth credentials supplied on the command line can appear in shell history or process listings, so prefer an isolated test environment. gzip and Brotli flags do not compress files; they only serve sibling .gz or .br files you built beforehand. There is no official public Docker image, so container users must maintain their own image.
Patterns
Serve a specific build directoryserve-directory
npx http-server ./dist -a 127.0.0.1 -p 8080 -c-1Specify the path instead of relying on the ./public-or-current-directory default. Binding to localhost avoids exposing the preview on every interface.
Find an available portchoose-open-port
npx http-server ./dist -a 127.0.0.1 -p 0 -c-1-p 0 searches from port 8080. The chosen port is printed, so this is better for humans than automation expecting a fixed URL.
Hide directory and dotfile listingsdisable-listings
npx http-server ./public -a 127.0.0.1 -d false -i false --no-dotfilesDirectory listings and auto-index are enabled by default. These flags reduce accidental browsing but do not turn the tool into a hardened public server.
Serve test fixtures with permissive CORSenable-cors
npx http-server ./fixtures -a 127.0.0.1 --cors -c-1--cors sets Access-Control-Allow-Origin: *. Use it for controlled development fixtures, not as a selective origin policy.
Add explicit response headersadd-response-headers
npx http-server ./dist -a 127.0.0.1 \
-H 'Cross-Origin-Resource-Policy: cross-origin' \
-H 'X-Content-Type-Options: nosniff'-H can be repeated. Quote each full header so the shell does not split its value.
Use the documented single-page-app fallbackserve-spa-fallback
npx http-server ./dist -a 127.0.0.1 --proxy http://127.0.0.1:8080?The trailing question mark is required by the documented catch-all trick. Test asset 404s because unresolved requests are proxied back to the same server.
Proxy requests that do not match local filesproxy-api-misses
npx http-server ./dist -a 127.0.0.1 \
--proxy http://127.0.0.1:3000 \
--proxy-options.changeOrigin trueThe proxy receives every unresolved local path, not only /api. Keep frontend asset names and backend routes from colliding.
Prefer prebuilt Brotli and gzip assetsserve-precompressed
npx http-server ./dist -a 127.0.0.1 --brotli --gzipThe flags do not create compressed files. Build app.js.br and app.js.gz beside app.js before starting the server; Brotli wins when both are accepted.
Serve with an existing TLS certificateenable-local-tls
npx http-server ./dist -a 127.0.0.1 --tls --cert cert.pem --key key.pemThe command does not obtain or trust certificates. A self-signed certificate must be generated and trusted separately.
Put a test directory behind basic authset-basic-auth
npx http-server ./private -a 127.0.0.1 --username demo --password local-onlyCommand-line passwords can be retained in shell history and exposed in process listings. Do not use this pattern for real credentials.
Pin safe preview defaults in package.jsonconfigure-from-script
{
"scripts": {
"preview:static": "http-server ./dist -a 127.0.0.1 -p 8080 -c-1 -d false --no-dotfiles"
},
"devDependencies": {
"http-server": "14.1.1"
}
}A local dev dependency makes CI and teammates use the locked version instead of whichever global command happens to be installed.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| serve | npm | You want a polished static-site CLI with straightforward single-page-app routing and modern defaults |
| sirv-cli | npm | You want a small static server with compression, single-page mode, and development-friendly flags |
| live-server | npm | You specifically need browser reload when local files change |