diff --git a/priv/www/index.html b/priv/www/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..414f86883e2cb0071f0bdec21a959e92e7841589
--- /dev/null
+++ b/priv/www/index.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title></title>
+    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic">
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.css">
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.1.0/milligram.css">
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.1.6/zepto.js"></script>
+</head>
+<body>
+<h1>Hello</h1>
+</body>
+</html>
diff --git a/rebar.config b/rebar.config
index e43e32a54e57f4573bb8cae82cd40a7206609fd6..a443400b4fe8ec28a3618d2e77a4eda927c83575 100644
--- a/rebar.config
+++ b/rebar.config
@@ -1,6 +1,7 @@
 {erl_opts, [debug_info]}.
 
 {escript_main_app, hijack}.
+{escript_incl_extra, [{"priv/www/*", "_build/default/lib/hijack/"}]}.
 
 {deps, [
     {getopt, "0.8.2"},
diff --git a/src/hijack.erl b/src/hijack.erl
index dc004829eede847982bdbdf7be867dd9a057841f..ec64e21bbad84700d031ba3d18a96799b85bbd68 100644
--- a/src/hijack.erl
+++ b/src/hijack.erl
@@ -5,6 +5,7 @@
     {consul, $c, "consul", {string, "localhost:8083"}, "Consul host and port"},
     {target, $t, "target", {string, "localhost:8080"}, "Target host and port"},
     {snoop, $s, "snoop", {boolean, false}, "Ignore response from target"},
+    {port, $w, "port", {integer, 4040}, "Port for hijack webserver"},
     {username, $u, "username", string, "Username"},
     {password, $p, "password", string, "Password"},
     {path, $r, "path", {string, ".*"}, "Path regexp"},
@@ -16,7 +17,9 @@
     transport = ranch_ssl,
     consul_socket = undefined,
     target_host = "localhost",
-    target_port = 80
+    target_port = 80,
+    httpd_pid,
+    httpd_port
 }).
 
 main(Args) ->
@@ -66,6 +69,48 @@ clear_stdin(Prompt) ->
             clear_stdin(Prompt)
     end.
 
+start_httpd(State = #state{opts = Opts}) ->
+    application:ensure_all_started(inets),
+    Port = proplists:get_value(port, Opts, 4040),
+    CommonConfig = [
+        {bind_address, "localhost"},
+        {port, Port},
+        {erl_script_alias, {"/esi", [hijack_www]}},
+        {server_name, "hijack"},
+        {server_root, "."}
+    ],
+    ServiceConfig = try escript:script_name() of
+                        File ->
+                            {ok, Sections} = escript:extract(File, []),
+                            Archive = proplists:get_value(archive, Sections),
+                            {ok, ZipHandle} = zip:zip_open(Archive, [memory]),
+                            [
+                                {modules, [mod_esi, mod_zipget]},
+                                {document_root, "."},
+                                {zip_handle, ZipHandle},
+                                {zip_root, "priv/www"}
+                            ]
+                    catch
+                        _:_ ->
+                            [
+                                {modules, [mod_esi, mod_get]},
+                                {document_root, "priv/www"}
+                            ]
+                    end,
+    case inets:start(httpd, CommonConfig ++ ServiceConfig) of
+        {ok, Pid} when Port == 0 ->
+            OtherPort = proplists:get_value(port, httpd:info(Pid)),
+            io:format("Default port busy, started webserver at http://localhost:~b~n", [OtherPort]),
+            State#state{httpd_pid = Pid, httpd_port = OtherPort};
+        {ok, Pid} ->
+            io:format("Started webserver at http://localhost:~b~n", [Port]),
+            State#state{httpd_pid = Pid, httpd_port = Port};
+        {error, _Reason} when Port /= 0 ->
+            start_httpd(State#state{opts = lists:keyreplace(port, 1, Opts, {port, 0})});
+        {error, _Reason} ->
+            io:format("Error!, unable to start hijack webserver")
+    end.
+
 execute(State = #state{opts = Opts}) ->
     Transport = ranch_ssl,
     {ConsulHost, ConsulPort} = parse_host_and_port(proplists:get_value(consul, Opts), 8083),
@@ -179,7 +224,7 @@ handle(State = #state{opts = Opts}, #{<<"action">> := <<"authorized">>, <<"usern
 
 handle(State, #{<<"action">> := <<"bind">>, <<"host">> := Host, <<"path">> := Path, <<"mode">> := Mode}) ->
     io:format("Ready, ~sing ~s/~s~n", [Mode, Host, Path]),
-    State;
+    start_httpd(State);
 
 handle(State = #state{transport = Transport, consul_socket = Socket}, #{<<"action">> := <<"error">>, <<"message">> := Message}) ->
     io:format("~s~n", [Message]),
diff --git a/src/hijack_www.erl b/src/hijack_www.erl
new file mode 100644
index 0000000000000000000000000000000000000000..c3d1ccde497bee971e989f7d41ae08c7a231d610
--- /dev/null
+++ b/src/hijack_www.erl
@@ -0,0 +1,12 @@
+-module(hijack_www).
+
+-export([
+    echo/3,
+    hello/3
+]).
+
+echo(SessionID, _Env, Input) ->
+    mod_esi:deliver(SessionID, Input).
+
+hello(SessionID, _Env, _Input) ->
+    mod_esi:deliver(SessionID, "world").
diff --git a/src/mod_zipget.erl b/src/mod_zipget.erl
new file mode 100644
index 0000000000000000000000000000000000000000..892359196a420be1290f00e71ecfaa876cc077e4
--- /dev/null
+++ b/src/mod_zipget.erl
@@ -0,0 +1,53 @@
+-module(mod_zipget).
+
+-export([do/1]).
+
+-include_lib("inets/include/httpd.hrl").
+
+do(Info) ->
+    case Info#mod.method of
+        "GET" ->
+            case proplists:get_value(status, Info#mod.data) of
+                {_StatusCode, _PhraseArgs, _Reason} ->
+                    {proceed, Info#mod.data};
+                undefined ->
+                    case proplists:get_value(response, Info#mod.data) of
+                        undefined ->
+                            do_get(Info);
+                        _Response ->
+                            {proceed, Info#mod.data}
+                    end
+            end;
+        _ ->
+            {proceed, Info#mod.data}
+    end.
+
+do_get(Info) ->
+    send_response(Info#mod.socket, Info#mod.socket_type, Info#mod.request_uri, Info).
+
+send_response(Socket, SocketType, "", Info) ->
+    send_response(Socket, SocketType, "/index.html", Info);
+
+send_response(Socket, SocketType, "/", Info) ->
+    send_response(Socket, SocketType, "/index.html", Info);
+
+send_response(Socket, SocketType, RequestURI, Info) ->
+    ZipHandle = httpd_util:lookup(Info#mod.config_db, zip_handle),
+    ZipRoot = httpd_util:lookup(Info#mod.config_db, zip_root, ""),
+    Path = ZipRoot ++ RequestURI,
+    case zip:zip_get(Path, ZipHandle) of
+        {ok, {Path, Content}} ->
+            Suffix = httpd_util:suffix(Path),
+            MimeType = httpd_util:lookup_mime_default(Info#mod.config_db, Suffix, "text/plain"),
+            Headers = [
+                {content_type, MimeType},
+                {content_length, integer_to_list(byte_size(Content))}
+            ],
+            httpd_response:send_header(Info, 200, Headers),
+            httpd_socket:deliver(SocketType, Socket, Content),
+            {proceed, [{response, {already_sent, 200, byte_size(Content)}}, {mime_type, MimeType} | Info#mod.data]};
+        {error, file_not_found} ->
+            {proceed, [{status, httpd_file:handle_error(enoent, "open", Info, Path)} | Info#mod.data]};
+        {error, Reason} ->
+            {proceed, [{status, httpd_file:handle_error(Reason, "open", Info, Path)} | Info#mod.data]}
+    end.