Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Media captured from the ether for your viewing pleasure
Erlang JavaScript
tree: 060f5c310c

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.


perv watches the network for web traffic and dumps the content to your
hard drive. On a hubbed or public wifi network, this includes everyone
else's web browsing too.

perv is really just a drifnet clone
( written in Erlang but differs
in that it parses the HTTP response rather than pulling media types out
of a binary stream.


1. Get the source code

git clone git://

2. Compile perv



perv:start_link() -> ok
perv:start_link(Options) -> ok

    Types   Options = list()

    See epcap documentation for options.

    Files are written to priv/files/<mime type>.

    A trace file containing the HTTP response is written to priv/tmp. The
    trace file can be unpacked by using pervon:content/3.

pervon:content(Path, Name, Response) -> ok

    Types   Path = string()
            Name = string()
            Response = binary()

    "Path" is a directory where the media in the HTTP response will
    be unpacked.

    "Name" is the suffix prepended to file names. Since the HTTP response
    can contain many files, the result of erlang:now/0 is appended to the
    name with the file type as the extension. The file type is derived
    from the "Content-Type" header.

    "Response" is the HTTP response.

peep:start() -> ok


To start sniffing, specify the interface to use:

> perv:start_link([{interface, "eth0"}]).

By default, all traffic on port 80 is captured. If you want to exclude
your IP address, modify the pcap filter. For example, if you are using
the device "en1" with an IP address of "":

> perv:start_link([{interface, "en1"}, {filter, "tcp and port 80 and not"}]).

perv includes a very basic web interface:

> peep:start().

Then open a browser: http://localhost:8889/

To unpack the HTTP response:

> {ok, Response} = file:read_file("priv/tmp/").
> pervon:content("/tmp/content_dir", "suffix", Response).


* peep is really ugly, fix it

* handle large files, possibly by periodically writing out the buffered
  data to disk in the fsm. Since the files are buffered, downloading
  very large files can exhaust the memory of the Erlang node, causing
  it to hang or crash.

* pervon:content/3 should return a list of tuples containing the name,
  file type and file contents, rather than writing them directly to disk

* file chunks are still occassionally dropped (Content-Length
  header does not match the body size), for example, when playing
  Flash video. Figure out where this is happening and see if it can be
  fixed. Might be a regression, since it was working reliably previously.

* since the interface being snooped is known, grab the device's IP
  address using inet:ifget/2. Provide an option for including/excluding
  the user's address.

Something went wrong with that request. Please try again.