mixu / electroshot

Capture website screenshots with optional device and network emulation as jpg, png or pdf (with web fonts!) using Electron / Chrome.
548 stars 34 forks source link

electroshot

Capture website screenshots with optional device and network emulation as JPG, PNG or PDF (with web fonts!) using Electron / Chrome.

Features

Changelog

Quickstart

Install electroshot via npm (to get npm, just install Node.js):

sudo npm install -g electroshot

Usage

Specify urls and screen resolutions as arguments - urls first. The CLI design was strongly influenced by the excellent pageres-cli CLI.

electroshot <url> <resolution | device preset>

electroshot google.com 1024x768
electroshot google.com 1024x768 1366x768 # 2 screenshots
electroshot google.com yahoo.com 1024x768 # 2 screenshots
electroshot google.com yahoo.com 1024x768 1366x768 # 4 screenshots

You can also capture screenshots with device emulation on. Device presets work just like resolutions:

electroshot google.com "iPhone 6"
electroshot google.com "horizontal iPhone 6" "Nexus 6" # 2 screenshots
electroshot google.com yahoo.com 1024x768 "Nokia N9" # 4 screenshots

To list all the device presets, run electroshot --list-devices. Prepending "horizontal" to the device name switches it to horizontal (landscape) orientation.

To use a custom device, set --device <json>, where the value is a JSON blob that defines a custom device, similar to how devices are listed in chromium-emulated-devices under extensions.device in index.json.

You can also pass in file paths. By default, file paths are served through an Express static file server on localhost to avoid the hassles that come with the file:// protocol. By default, the directory that contains the file becomes the webroot of the server.

electroshot /path/index.html 1024x768 # mounts /path onto localhost:3000/
electroshot file:///path/index.html 1024x768 # skips mounting, and loads a file:// url

You can capture a local file directly without a static file server by explicitly starting files with the file:// protocol.

You can set the web server root by setting --root /path explicitly.

electroshot /foo/bar/index.html 1024 --root /foo

Cropping

By default, what you say is what you get - the screenshots are clipped to the specified size. To generate a screenshot of the whole page (e.g. as tall needed for the page), just leave out the height:

electroshot google.com 800x
electroshot google.com 800 # also works
electroshot google.com "cropped iPhone 6" # cropped to iPhone 6 screen height
electroshot google.com "iPhone6"x800 # cropped to 800 px tall

Emulated devices can also be cropped. Prepending "cropped" to the device name will produce a screenshot that is the size of a single screen for that device. You can also set a specific pixel height as shown in the example above.

Capture groups

You can group arguments with square brackets:

electroshot [ <url> <resolution> ] [ <url> <resolution> ]
electroshot [ <url> <resolution> ... ]

# Mix grouped and single arguments
electroshot [ google.com 1024x768 1600x900 ] google.com 1366x768

# Options defined inside a group will override the outer ones.
electroshot [ google.com 1024x --format png ] google.com 1366x --format jpg

Capture options

Location and file name

You can set the output directory by setting --out <dir> (default: process.cwd).

You can explicitly set the full path for each screenshot using --filename <path>. Relative paths in file names are relative to --out, full paths are preserved as-is.

electroshot google.com 1024 --out /foo/bar
# -> writes /foo/bar/screenshot.png
electroshot google.com 1024 --out /foo/bar --filename "screenshot.png"
# -> writes /foo/bar/google.com-linux.png
electroshot google.com 1024 --filename "/foo/bar/{name}-{platform}.{format}"

You can also use the following tokens to specify a template for filenames. The default template is {name}-{size}.{format}; if you set a --delay, it is {name}-{size}-at-{delay}ms.{format}.

If the generated filenames are not unique, a number will be appended to the paths, e.g. foo.com-1024x768-1.png and foo.com-1024x768-2.png.

Page rendering: delay, selector, zoom-factor

You can capture a specific DOM element via --selector <expr>. The selector is passsed to document.querySelector. The screenshot is cropped and sized to match the element as it appears on the page.

You can set the default zoom factor of the page using --zoom-factor <n>. 1.0 represents 100% and 3.0 represents 300%.

On OSX, you should also be aware of the Chrome flag --force-device-scale-factor <n> which forces Chrome to use a specific high dpi scale factor. You can pass Chrome flags to electroshot and they will be passed through to Electron / Chrome.

To introduce a delay to the page capture, specify --delay <ms>. The default value is 0, which simply waits until two requestAnimationFrame calls have passed. This is usually enough time to capture something reasonable.

You can set multiple --delays to capture the page(s) at multiple points in time. Combined with --emulate-network, this can produce a full timeline of loading a specific page under slow network access.

electroshot --emulate-network "Good 3G" theverge.com "cropped Nexus 6" --delay 1000 --delay 3000 --delay 5000 --delay 6000 --delay 8000 --delay 0

Note that there are some limitations when using --delay. Specifically:

This is because those features require electroshot to inject a content script, and Electron's executeJavaScript API waits until the page is fully loaded before executing injected scripts - so I had to pick between having those features available or having accurate timing information. Let me know if you can figure out a better way to handle those features.

Format-specific options

You can capture screenshots as JPG, PNG, or PDF by setting --format <png|jpg|pdf>. The following options control format-specific options.

Network emulation

To list all the known network condition presets, run electroshot --list-networks.

Use --emulate-network <preset> to set a specific network profile.

electroshot --emulate-network "Good 3G" theverge.com "cropped iPhone 6"

You can also set the network parameters individually:

Capturing using an headless server / vagrant / docker

Most headless (e.g. no X11) environments will need some additional packages to be installed for electroshot to work. Here's one example snippet:

# Install dependencies
apt-get update &&\
    apt-get install -y libgtk2.0-0 libgconf-2-4 \
    libasound2 libxtst6 libxss1 libnss3 xvfb ttf-mscorefonts-installer

# Start Xvfb
Xvfb -ac -screen scrn 1280x2000x24 :9.0 &
export DISPLAY=:9.0

Related issue on Electron: https://github.com/atom/electron/issues/228

HTTP options

You can set a custom user agent using --user-agent <string>.

You can set a custom cookie using --cookie <cookie>. This can be set multiple times.

The local file server starts on localhost port 3000 by default if you pass in local file paths. You can set the hostname and port using --host <hostname> and --port <port>. As discussed earlier, you can control the mount point by setting --root <dir>.

If you need to ignore SSL errors, you can set the Chrome flag --ignore-certificate-errors.

Content injection

You can inject CSS and JS into the page using the following options:

Misc

Passing thru Chrome flags

electroshot passes any unknown flags on to Chrome via Electron. Here are three useful flags:

For more, see: https://github.com/atom/electron/blob/master/docs/api/chrome-command-line-switches.md and http://peter.sh/experiments/chromium-command-line-switches/.

API

TODO for now; will probably look something like: