node package manager
Don’t reinvent the wheel. Reuse code within your team. Create a free org »


Browsertime - Your browser, your page, your scripts!

Build status Downloads Downloads total Stars


Access the Web Performance Timeline, from your browser, in your terminal!

Browsertime allows you to:

  1. Query timing data directly from the browser, to access Navigation Timing, User Timing, Resource Timing, first paint and RUM Speed Index.
  2. Generate HAR files (using HAR Export trigger for Firefox and parsing the Chrome log for Chrome).
  3. Run custom Javascript scripts in the browser and get statistics for each run.
  4. Record a video of the screen and analyze the result to get First Visual Change, Speed Index, Visual Complete 85 % and Last Visual Change.

A simple example

Use our Docker image (with Chrome, Firefox, XVFB and the dependencies needed to record a video):

$ docker run --shm-size=1g --rm -v "$(pwd)":/browsertime sitespeedio/browsertime --video --speedIndex

Or using node:

$ bin/browsertime.js

Load in Chrome three times. Results are stored in a JSON file (browsertime.json) with the timing data, and a HAR file (browsertime.har) in browsertime-results/$date/

I want more examples

Checkout the examples.


Browsertime supports Firefox and Chrome on desktop. On Android we support Chrome.

But we want to support Opera (on Android) and when(?!) iOS Safari supports WebDriver we will add that too.

How does it work

Browsertime uses Selenium NodeJS to drive the browser. It starts the browser, load a URL, executes configurable Javascripts to collect metrics, collect a HAR file.

To get the HAR from Firefox we use the HAR Export Trigger and Chrome we use Chrome-HAR to parse the timeline log and generate the HAR file.

Oh and you can run your own Selenium script before (--preScript) and after (--postScript) a URL is accessed so you can login/logout or do whatever you want.

Speed Index and video

It's easiest to run our ready made Docker container to be able to record a video and calculate SpeedIndex because then you get all dependencies needed for free to run VisualMetrics.

The default video will include a timer and showing when the metrics happens, but you can turn that off using --video.addTimer false.

Test using Docker

You can build and test changes using Docker locally.

$ docker build -t sitespeedio/browsertime .
$ docker run --shm-size=1g --rm -v "$(pwd)":/browsertime sitespeedio/browsertime -n 1 --video --speedIndex


You can throttle the connection to make the connectivity slower to make it easier to catch regressions. The best way to do that is to setup a network bridge in Docker.

Default we use TSProxy because it's only dependency is Python 2.7 but we have a problem with that together with Selenium, so that it is kind of unusable right now. Help us fix that in #229.

If you run Docker you can use tc as connectivity engine but that will only set the latency, if you want to set the download speed you need to create a network bridge in Docker.

Here's an full example to setup up Docker network bridges on a server that has tc installed:

echo 'Starting Docker networks'
docker network create --driver bridge --subnet= --gateway= --opt ""="docker1" 3g
tc qdisc add dev docker1 root handle 1: htb default 12
tc class add dev docker1 parent 1:1 classid 1:12 htb rate 1.6mbit ceil 1.6mbit
tc qdisc add dev docker1 parent 1:12 netem delay 300ms
docker network create --driver bridge --subnet= --gateway= --opt ""="docker2" cable
tc qdisc add dev docker2 root handle 1: htb default 12
tc class add dev docker2 parent 1:1 classid 1:12 htb rate 5mbit ceil 5mbit
tc qdisc add dev docker2 parent 1:12 netem delay 28ms
docker network create --driver bridge --subnet= --gateway= --opt ""="docker3" 3gfast
tc qdisc add dev docker3 root handle 1: htb default 12
tc class add dev docker3 parent 1:1 classid 1:12 htb rate 1.6mbit ceil 1.6mbit
tc qdisc add dev docker3 parent 1:12 netem delay 150ms
docker network create --driver bridge --subnet= --gateway= --opt ""="docker4" 3gem
tc qdisc add dev docker4 root handle 1: htb default 12
tc class add dev docker4 parent 1:1 classid 1:12 htb rate 0.4mbit ceil 0.4mbit
tc qdisc add dev docker4 parent 1:12 netem delay 400ms

Then when you run your container you add the network with --network cable. You should also tell Browsertime that you set the connectivity external from BT. A full example running running with cable:

$ docker run --shm-size=1g --network=cable --rm sitespeedio/browsertime -c cable --connectivity.engine external --speedIndex --video

And using the 3g network:

$ docker run --shm-size=1g --network=3g --rm sitespeedio/browsertime -c 3g --connectivity.engine external --speedIndex --video

And if you want to remove the networks:

echo 'Stopping Docker networks'
docker network rm 3g
docker network rm 3gfast
docker network rm 3gem
docker network rm cable

Test on your mobile device

Browsertime supports Chrome on Android: Collecting SpeedIndex, HAR and video! This is still really new, let us know if you find any bugs.

You need to install adb and prepare your phone before you start.

If you want to set connectivity you need to use something like Micro device lab or TSProxy.

$ browsertime --video --speedIndex

If you are on Linux (we have tested Ubuntu 16) you can use our Docker container to drive your Android phone. A couple of things to remember:

  • You need to run in privileged mode --privileged
  • You need to share the USB ports -v /dev/bus/usb:/dev/bus/usb
  • Add -e START_ADB_SERVER=true to start the adb server
  • Turn of xvfb --xvfb false (we start that automatically)

If you use Docker you will automatically get support for video and SpeedIndex. You can get that without Docker but then need to install VisualMetrics dependencies yourself.

$ docker run --privileged -v /dev/bus/usb:/dev/bus/usb -e START_ADB_SERVER=true --shm-size=1g --rm -v "$(pwd)":/browsertime-results sitespeedio/browsertime -n 1 --xvfb false --speedIndex --video


Run $ bin/browsertime.js --help and you can see the configuration options:

browsertime [options] 

  --timeouts.browserStart       Timeout when waiting for browser to start, in milliseconds                                                                         [number] [default: 60000]
  --timeouts.pageLoad           Timeout when waiting for url to load, in milliseconds                                                                             [number] [default: 300000]
  --timeouts.script             Timeout when running browser scripts, in milliseconds                                                                              [number] [default: 80000]
  --timeouts.pageCompleteCheck  Timeout when waiting for page to complete loading, in milliseconds                                                                [number] [default: 300000]

  --chrome.args                        Extra command line arguments to pass to the Chrome process (e.g. --no-sandbox). To add multiple arguments to Chrome, repeat --chrome.args once per
  --chrome.binaryPath                  Path to custom Chrome binary (e.g. Chrome Canary). On OS X, the path should be to the binary inside the app bundle, e.g. /Applications/Google Chrome
                              Chrome Canary
  --chrome.chromedriverPath            Path to custom Chromedriver binary. Make sure to use a Chromedriver version that's compatible with the version of Chrome you're using
  --chrome.mobileEmulation.deviceName  Name of device to emulate. Works only standalone (see list in Chrome DevTools, but add company like 'Apple iPhone 6')
  --chrome.mobileEmulation.width       Width in pixels of emulated mobile screen (e.g. 360)                                                                                         [number]
  --chrome.mobileEmulation.height      Height in pixels of emulated mobile screen (e.g. 640)                                                                                        [number]
  --chrome.mobileEmulation.pixelRatio  Pixel ratio of emulated mobile screen (e.g. 2.0)             Run Chrome on your Android device. Set to for default Chrome version. You need to run adb start-server before you start.        Choose which device to use. If you do not set it, first device will be used.
  --chrome.collectTracingEvents        Include Tracing events in the performance log (implies chrome.collectPerfLog).                                                              [boolean]
  --chrome.traceCategories             A comma separated list of Tracing event categories to include in the performance log (implies chrome.collectTracingEvents).                  [string]
  --chrome.collectPerfLog              Collect performance log from Chrome with Page and Network events and save to disk.                                                          [boolean]
  --chrome.collectNetLog               Collect network log from Chrome and save to disk.                                                                                           [boolean]

  --firefox.binaryPath             Path to custom Firefox binary (e.g. Firefox Nightly). On OS X, the path should be to the binary inside the app bundle, e.g.
  --firefox.preference             Extra command line arguments to pass Firefox preferences by the format key:value To add multiple preferences, repeat --firefox.preference once per
  --firefox.includeResponseBodies  Include response bodies in HAR                                                                                                                  [boolean]

  --selenium.url  URL to a running Selenium server (e.g. to run a browser on another machine).

  --proxy.http   Http proxy (host:port)                                                                                                                                             [string]
  --proxy.https  Https proxy (host:port)                                                                                                                                            [string]

  --connectivity.profile, -c     The connectivity profile.                                [choices: "3g", "3gfast", "3gslow", "3gem", "2g", "cable", "native", "custom"] [default: "native"]
  --connectivity.downstreamKbps  This option requires --connectivity.profile be set to "custom".
  --connectivity.upstreamKbps    This option requires --connectivity.profile be set to "custom".
  --connectivity.latency         This option requires --connectivity.profile be set to "custom".
  --connectivity.alias           Give your connectivity profile a custom name       The connectivity device. Used for engine tc.                                                                                              [default: "eth0"]
  --connectivity.engine          The engine for connectivity. TC (Linux Traffic Control) needs tc work but will only setup upload and latency. Use external if you set the connectivity
                                 outside of Browsertime. The best way do to this is described in
                                                                                                                                           [choices: "tc", "external"] [default: "external"]

  --video                Record a video. Requires FFMpeg to be installed                                                                                                           [boolean]
  --videoRaw             Do not add timer and metrics to the video                                                                                                                 [boolean]
  --speedIndex           Calculate SpeedIndex. Requires FFMpeg and python dependencies                                                                                             [boolean]
  --browser, -b          Specify browser                                                                                                  [choices: "chrome", "firefox"] [default: "chrome"]
  --screenshot           Save one screen shot per iteration.                                                                                                                       [boolean]
  --pageCompleteCheck    Supply a Javascript that decides when the browser is finished loading the page and can start to collect metrics. The Javascript snippet is repeatedly queried to
                         see if page has completed loading (indicated by the script returning true). Use it to fetch timings happening after the loadEventEnd.
  --iterations, -n       Number of times to test the url (restarting the browser between each test)                                                                    [number] [default: 3]
  --prettyPrint          Enable to print json/har with spaces and indentation. Larger files, but easier on the eye.                                               [boolean] [default: false]
  --delay                Delay between runs, in milliseconds                                                                                                           [number] [default: 0]
  --preScript            Selenium script(s) to run before you test your URL (use it for login, warm the cache, etc). Note that --preScript can be passed multiple times.
  --postScript           Selenium script(s) to run after you test your URL (use it for logout etc). Note that --postScript can be passed multiple times.
  --script               Add custom Javascript to run after the page has finished loading to collect metrics. If a single js file is specified, it will be included in the category named
                         "custom" in the output json. Pass a folder to include all .js scripts in the folder, and have the folder name be the category. Note that --script can be passed
                         multiple times.
  --userAgent            Override user agent
  --silent, -q           Only output info in the logs, not to the console. Enter twice to suppress summary line.                                                                     [count]
  --output, -o           Specify file name for Browsertime data (ex: 'browsertime'). Unless specified, file will be named browsertime.json
  --har                  Specify file name for .har file (ex: 'browsertime'). Unless specified, file will be named browsertime.har
  --skipHar              Pass --skipHar to not collect a HAR file.                                                                                                                 [boolean]
  --config               Path to JSON config file
  --viewPort             Size of browser window WIDTHxHEIGHT or "maximize". Note that "maximize" is ignored for xvfb.
  --resultDir            Set result directory for the files produced by Browsertime
  --xvfb                 Start xvfb before the browser is started                                                                                                 [boolean] [default: false]
  --preURL               A URL that will be accessed first by the browser before the URL that you wanna analyze. Use it to fill the cache.
  --userTimingWhitelist  All userTimings are captured by default this option takes a regex that will whitelist which userTimings to capture in the results.
  -h, --help             Show help                                                                                                                                                 [boolean]
  -V, --version          Show version number                                                                                                                                       [boolean]

Send metrics to Graphite

The easiest way to send metrics is to install jq and use it to pick the values you wanna track.

Here's an example on how you can pickup the median SpeedIndex from Browsertime and send it to your Graphite instance.

echo "browsertime.your.key.SpeedIndex.median" $(cat /tmp/browsertime/browsertime.json | jq .statistics.visualMetrics.SpeedIndex.median) "`date +%s`" | nc -q0 2003