Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Big list of http static server one-liners

Each of these commands will run an ad hoc http static server in your current (or specified) directory, available at http://localhost:8000. Use this power wisely.

Discussion on reddit.

Python 2.x

$ python -m SimpleHTTPServer 8000

Python 3.x

$ python -m http.server 8000

Twisted (Python)

$ twistd -n web -p 8000 --path .

Or:

$ python -c 'from twisted.web.server import Site; from twisted.web.static import File; from twisted.internet import reactor; reactor.listenTCP(8000, Site(File("."))); reactor.run()'

Depends on Twisted.

Ruby

$ ruby -rwebrick -e'WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd).start'

Credit: Barking Iguana

Ruby 1.9.2+

$ ruby -run -ehttpd . -p8000

Credit: nobu

adsf (Ruby)

$ gem install adsf   # install dependency
$ adsf -p 8000

Credit: twome

No directory listings.

Sinatra (Ruby)

$ gem install sinatra   # install dependency
$ ruby -rsinatra -e'set :public_folder, "."; set :port, 8000'

No directory listings.

Perl

$ cpan HTTP::Server::Brick   # install dependency
$ perl -MHTTP::Server::Brick -e '$s=HTTP::Server::Brick->new(port=>8000); $s->mount("/"=>{path=>"."}); $s->start'

Credit: Anonymous Monk

Plack (Perl)

$ cpan Plack   # install dependency
$ plackup -MPlack::App::Directory -e 'Plack::App::Directory->new(root=>".");' -p 8000

Credit: miyagawa

Mojolicious (Perl)

$ cpan Mojolicious::Lite   # install dependency
$ perl -MMojolicious::Lite -MCwd -e 'app->static->paths->[0]=getcwd; app->start' daemon -l http://*:8000

No directory listings.

http-server (Node.js)

$ npm install -g http-server   # install dependency
$ http-server -p 8000

Note: This server does funky things with relative paths. For example, if you have a file /tests/index.html, it will load index.html if you go to /test, but will treat relative paths as if they were coming from /.

node-static (Node.js)

$ npm install -g node-static   # install dependency
$ static -p 8000

No directory listings.

PHP (>= 5.4)

$ php -S 127.0.0.1:8000

Credit: /u/prawnsalad and MattLicense

No directory listings.

Erlang

$ erl -s inets -eval 'inets:start(httpd,[{server_name,"NAME"},{document_root, "."},{server_root, "."},{port, 8000},{mime_types,[{"html","text/html"},{"htm","text/html"},{"js","text/javascript"},{"css","text/css"},{"gif","image/gif"},{"jpg","image/jpeg"},{"jpeg","image/jpeg"},{"png","image/png"}]}]).'

Credit: nivertech (with the addition of some basic mime types)

No directory listings.

busybox httpd

$ busybox httpd -f -p 8000

Credit: lvm

webfs

$ webfsd -F -p 8000

Depends on webfs.

IIS Express

C:\> "C:\Program Files (x86)\IIS Express\iisexpress.exe" /path:C:\MyWeb /port:8000

Depends on IIS Express.

Credit: /u/fjantomen

No directory listings. /path must be an absolute path.

Meta

If you have any suggestions, drop them in the comments below or on the reddit discussion. To get on this list, a solution must:

  1. serve static files using your current directory (or a specified directory) as the server root,
  2. be able to be run with a single, one line command (dependencies are fine if they're a one-time thing),
  3. serve basic file types (html, css, js, images) with proper mime types,
  4. require no configuration (from files or otherwise) beyond the command itself (no framework-specific servers, etc)
  5. must run, or have a mode where it can run, in the foreground (i.e. no daemons)
@vistun
Copy link

vistun commented Feb 28, 2021

This a good one @vandot
edited below, works with semicolons

It still oneliner :)
golang
echo 'package main; import "net/http"; func main() {fs := http.FileServer(http.Dir(".")); http.Handle("/", fs); http.ListenAndServe(":8000", nil)}' > main.go; go run main.go; rm main.go

@textprotocol
Copy link

textprotocol commented Apr 2, 2021

ucspi-tcp text://protocol server.

# tcpserver -v -c42 -o -D -H -P -l 0 -R 127.0.0.1 1961 timeout 1 ../../bin/publictext

https://github.com/textprotocol/publictext

@johnwyles
Copy link

johnwyles commented May 13, 2021

@lethalman

I'd like to request a bash http server using /dev/tcp, anybody has a one-liner for that?

https://unix.stackexchange.com/a/49947

@marin-liovic
Copy link

marin-liovic commented May 13, 2021

replace all of the npm install with npx for a oneliner, e.g. npx superstatic -p 8000

@eikes
Copy link

eikes commented May 13, 2021

PowerShell

$Hso=New-Object Net.HttpListener;$Hso.Prefixes.Add("http://+:8000/");$Hso.Start();While ($Hso.IsListening){$HC=$Hso.GetContext();$HRes=$HC.Response;$HRes.Headers.Add("Content-Type","text/plain");$Buf=[Text.Encoding]::UTF8.GetBytes((GC (Join-Path $Pwd ($HC.Request).RawUrl)));$HRes.ContentLength64=$Buf.Length;$HRes.OutputStream.Write($Buf,0,$Buf.Length);$HRes.Close()};$Hso.Stop()

PowerShell from cmd.exe

PowerShell.exe -nop -enc JABIAHMAbwA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAEgAdAB0AHAATABpAHMAdABlAG4AZQByADsAJABIAHMAbwAuAFAAcgBlAGYAaQB4AGUAcwAuAEEAZABkACgAIgBoAHQAdABwADoALwAvACsAOgA4ADAAMAAwAC8AIgApADsAJABIAHMAbwAuAFMAdABhAHIAdAAoACkAOwBXAGgAaQBsAGUAIAAoACQASABzAG8ALgBJAHMATABpAHMAdABlAG4AaQBuAGcAKQB7ACQASABDAD0AJABIAHMAbwAuAEcAZQB0AEMAbwBuAHQAZQB4AHQAKAApADsAJABIAFIAZQBzAD0AJABIAEMALgBSAGUAcwBwAG8AbgBzAGUAOwAkAEgAUgBlAHMALgBIAGUAYQBkAGUAcgBzAC4AQQBkAGQAKAAiAEMAbwBuAHQAZQBuAHQALQBUAHkAcABlACIALAAiAHQAZQB4AHQALwBwAGwAYQBpAG4AIgApADsAJABCAHUAZgA9AFsAVABlAHgAdAAuAEUAbgBjAG8AZABpAG4AZwBdADoAOgBVAFQARgA4AC4ARwBlAHQAQgB5AHQAZQBzACgAKABHAEMAIAAoAEoAbwBpAG4ALQBQAGEAdABoACAAJABQAHcAZAAgACgAJABIAEMALgBSAGUAcQB1AGUAcwB0ACkALgBSAGEAdwBVAHIAbAApACkAKQA7ACQASABSAGUAcwAuAEMAbwBuAHQAZQBuAHQATABlAG4AZwB0AGgANgA0AD0AJABCAHUAZgAuAEwAZQBuAGcAdABoADsAJABIAFIAZQBzAC4ATwB1AHQAcAB1AHQAUwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAEIAdQBmACwAMAAsACQAQgB1AGYALgBMAGUAbgBnAHQAaAApADsAJABIAFIAZQBzAC4AQwBsAG8AcwBlACgAKQB9ADsAJABIAHMAbwAuAFMAdABvAHAAKAApAA==

What a handy one-liner!

@rjmunro
Copy link

rjmunro commented May 13, 2021

Note that if you want to share something with another machine, most of the solutions that bind to localhost or 127.0.0.1 won't work. Normally if you change localhost or 127.0.0.1 to 0, it will listen on all interfaces so you can download something from another machine.

E.g. change:

php -S 127.0.0.1:8000

to:

php -S 0:8000

@radiosilence
Copy link

radiosilence commented May 13, 2021

npx serve

Yep, this is probably the easiest

@radiosilence
Copy link

radiosilence commented May 13, 2021

npx serve

Yep, this is probably the easiest

@mmazzarolo
Copy link

mmazzarolo commented May 13, 2021

With serverino:

npx serverino --port 8000

Use --secure to automatically generate a certificate and serve on SSL (at https://localhost:8000).

@pimbrouwers
Copy link

pimbrouwers commented May 13, 2021

With Sergio - a Kestrel wrapper using Argu:

sergio

This will serve the current directory at https://[::]:8080.

To specify listener details:

sergio --listener localhost 8080

To display all options:

sergio --help

@dbohdan
Copy link

dbohdan commented May 13, 2021

Tcl

You will need Tcl 8.6 with Tcllib 1.19 or later.

echo 'package require httpd 4; ::httpd::server create HTTPD port 8000 myaddr 127.0.0.1 doc_root [pwd]; vwait forever' | tclsh

Credit to @rkeene.

@darkblue-b
Copy link

darkblue-b commented May 13, 2021

C99

klange/cgiserver

@vi
Copy link

vi commented May 13, 2021

websocat can serve specific explicit list of files on explicit URLs with explicit Content-Types.

websocat -s 1234 -F /index.html:text/html:./index.html -F /script.js:text/javascript:/path/to/thescript.js

There is no ability to automatically include more files based on existence on the filesystem, but sometimes 100% explicit approach may be beneficial.

@carlosneves0
Copy link

carlosneves0 commented May 13, 2021

docker run --rm --volume "$(pwd):/www:ro" --publish 80:80 docker.io/p3terx/darkhttpd:1.13 /www
docker image ls --format 'table {{.Repository}}:{{.Tag}}\t{{.Size}}' p3terx/darkhttpd:1.13
REPOSITORY:TAG          SIZE
p3terx/darkhttpd:1.13   91.7kB

docker run --rm --volume "$(pwd):/usr/share/nginx/html:ro" --publish 80:80 docker.io/library/nginx:1.20.0-alpine
docker image ls --format 'table {{.Repository}}:{{.Tag}}\t{{.Size}}' nginx:1.20.0-alpine
REPOSITORY:TAG        SIZE
nginx:1.20.0-alpine   22.6MB

@lpereira
Copy link

lpereira commented May 13, 2021

Lwan can be used as an one-liner web server, too: lwan -r /path/to/files/to/serve.

@wtarreau
Copy link

wtarreau commented May 14, 2021

Surprised that the once most universal thttpd wasn't even mentioned given how simple and convenient it is:

$ thttpd
$ netstat -ltnp | grep thttpd
tcp6       0      0 :::8080                 :::*                    LISTEN      25130/thttpd        

@wtarreau
Copy link

wtarreau commented May 14, 2021

A listening socket is exactly the type of thing I wouldn't want to see in a web browser!

@Offirmo
Copy link

Offirmo commented May 15, 2021

Node serve https://www.npmjs.com/package/serve much more professional that the other listed node.js options at this time.

Note that npm doesn't require you to install the package, so a true one-liner would be:

npx serve  --listen 8000
npx node-static -p 8000
npx http-server -p 8000

Thanks for the page!

@wtarreau
Copy link

wtarreau commented May 15, 2021

@nilslindemann:

@wtarreau why?

Browsers' security is extremely brittle, and it's already extremely hard for them to protect themselves from abuses by rogue sites and fake ads or limiting the impact of poorly written plugins that always risk to be used to steal user information. By opening them to the outside world using an incoming connection, you're suddenly bypassing a lot of the isolation efforts made in the browser by immediately exposing the process to the outside world. You just need a small bug in the server or a small overlook in the isolation between the server and the rest of the browser and your browser's sensitive info such as passwords, cookies, certificates, or history can immediately leak, or some dummy certs and cookies, or trojans can be inserted.

@pfreitag
Copy link

pfreitag commented May 19, 2021

For a ColdFusion / CFML powered web server in the current directory you can use commandbox:

box server start port=8123

The box binary (dependency) can be installed by running brew install commandbox or via several other methods: https://commandbox.ortusbooks.com/setup/installation

@michal-grzejszczak
Copy link

michal-grzejszczak commented Jul 31, 2021

Winstone, a wrapper around Jetty. Install:

mvn dependency:get -Dartifact=org.jenkins-ci:winstone:5.20 -DremoteRepositories=https://repo.jenkins-ci.org/public/

and run

java -jar ~/.m2/repository/org/jenkins-ci/winstone/5.20/winstone-5.20.jar --webroot=.

@patrickhener
Copy link

patrickhener commented Nov 9, 2021

Another option in go is goshs

@meydjer
Copy link

meydjer commented Dec 17, 2021

Just found nws which supports basepath:

If you want all requests to resolve to a base path (i.e. http://localhost:3030/basepath) without having to place all files into a src/basepath sub-directory, use the -b flag:

nws -b basepath

@nahteb
Copy link

nahteb commented Mar 30, 2022

In Java 18:

jwebserver -p 8080

@Object905
Copy link

Object905 commented May 20, 2022

When running in docker compose along with nominatim-docker

FROM nginx:1.21-alpine

RUN wget https://github.com/osm-search/nominatim-ui/releases/download/v3.2.4/nominatim-ui-3.2.4.tar.gz &&\
    tar -xvf nominatim-ui-3.2.4.tar.gz --strip-components=1 &&\
    cp -r dist/* /usr/share/nginx/html/ &&\
    sed -i 's/http:\/\/localhost\/nominatim\//http:\/\/nominatim:8080\//g' /usr/share/nginx/html/config.defaults.js

EXPOSE 80

@georgefst
Copy link

georgefst commented May 26, 2022

Haskell, with just Cabal:

echo 'WaiAppStatic.CmdLine.runCommandLine (const id)' | cabal repl -b wai-app-static

It's a bit verbose, but on the plus side you're in a REPL, so it's easy to modify things.

Prompted by a question on Reddit.

@dkorpel
Copy link

dkorpel commented Aug 7, 2022

D, with package 'serve':

dub run serve
dub run serve -- path/to/index.html

https://code.dlang.org/packages/serve

@tblaisot
Copy link

tblaisot commented Sep 9, 2022

for SPA static workload and without dependencies:
npx servor <root> <fallback> <port>
https://www.npmjs.com/package/servor

@x-yuri
Copy link

x-yuri commented Sep 16, 2022

Failed to install HTTP::Server::Brick in an Alpine container:

Unimplemented: POSIX::tmpnam(): use File::Temp instead at t/serving.t line 87.

And it might be abandoned.

@fkpussys
Copy link

fkpussys commented Sep 17, 2022

This is off topic but if we upload an image to a reposiory, how do we associate it with a script, like for example a game has a character and a script, how do we do that?? also f4f?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment