# Command line (CLI)

`localscreenshot` is the command line client of the API. One command takes a screenshot of a public web page and saves the image in the current folder. It uses the same API key and the same credits as everything else.

**In short**

```text
Run       npx localscreenshot https://example.com
Install   npm install -g localscreenshot, or pip install localscreenshot
Key       LOCALSCREENSHOT_API_KEY, or localscreenshot login
```

## 1. Install

**With npx.** Node 18.17 or later, nothing to install first. In a terminal, npx asks once before it downloads the package: `npx -y` skips the question.

```bash
npx localscreenshot https://example.com
```

**With npm.** Installs the command globally.

```bash
npm install -g localscreenshot
```

**With pip.** Python 3.9 or later, no dependencies.

```bash
pip install localscreenshot
```

**With pipx.** Runs it once without installing anything for good.

```bash
pipx run localscreenshot https://example.com
```

**With uv.** The same, with uv.

```bash
uvx localscreenshot https://example.com
```

The command has no dependencies. It sends no usage data and does not check for updates.

The rest of this page writes `localscreenshot`. If you did not install it, write `npx localscreenshot`, `pipx run localscreenshot` or `uvx localscreenshot` instead.

## 2. Set your key

Create a key in the [dashboard](https://localscreenshot.com/dashboard), under **Connect**. Then either put it in your environment:

```bash
export LOCALSCREENSHOT_API_KEY="your key"
```

or save it once on this machine:

```bash
localscreenshot login
```

`login` asks for the key without showing it, checks it against the API, and writes it to a file only you can read: `~/.config/localscreenshot/config.json` on macOS and Linux (under `$XDG_CONFIG_HOME` if you set it), `%APPDATA%\localscreenshot\config.json` on Windows. `localscreenshot logout` removes it. In a script or in CI, use the environment variable.

The key is never accepted as an argument, so it does not end up in your shell history. More on keys: [Your API key](https://docs.localscreenshot.com/auth).

## 3. Take a screenshot

```bash
localscreenshot https://example.com
```

It saves the image as `example.com-<date>-<time>.png` and says what it cost.

**What it prints**

```text
Saved /home/you/example.com-20261012-133800.png
1440 x 900, 88,627 bytes
Credits: 1 used, 47 left
```

Add options as flags:

```bash
# The whole page, as a JPEG
localscreenshot https://example.com --full-page --format jpeg

# As seen from Brazil
localscreenshot https://www.netflix.com --country BR

# On a phone, in dark mode, without the cookie banner
localscreenshot https://example.com --device iphone_15 --dark --no-cookie-banners

# Choose the file name
localscreenshot https://example.com -o home.png
```

To click one element before the picture, give the text a visitor reads on it: `localscreenshot https://www.notion.com --click-text "Product"`. A screenshot with a click costs 1 credit more.

## Options

| Option | What it does |
| --- | --- |
| `-o, --output <file>` | Where to write the image. Default: `<host>-<time>.<ext>` in the current folder. |
| `--country <code>` | Load the page from this country, two letters (`BR`, `DE`, `JP`). |
| `--full-page` | Capture the whole page, not only the first screen. |
| `--device <name>` | Screen to render on, for example `iphone_15`, `ipad`, `desktop_hd`. |
| `--format <format>` | `png` (default), `jpeg`, `webp` or `pdf`. |
| `--click-text <text>` | Click the one element showing this text, then capture. |
| `--no-cookie-banners` | Hide cookie banners. |
| `--no-ads` | Hide ads. |
| `--dark` | Render in dark mode. |
| `--json` | Print the answer of the API as JSON, with the path of the saved file. |
| `--force` | Overwrite the output file if it exists. |
| `-h, --help` | Show the help. |
| `-v, --version` | Show the version. |

Device names are on [Devices and sizes](https://docs.localscreenshot.com/devices), country codes on [Countries and attestation](https://docs.localscreenshot.com/countries). The API has more options than the command: for those, call it directly, as shown on [Take a screenshot](https://docs.localscreenshot.com/take).

The command does not overwrite a file. If the output file already exists, it stops and tells you to use `--force` or another name with `-o`. It checks before asking for the screenshot, so nothing is taken and no credit is used. The same goes for a path that is a folder, or whose folder does not exist.

## Other commands

| Command | What it does |
| --- | --- |
| `localscreenshot countries` | Lists the 227 countries a page can be loaded from. Needs no key. |
| `localscreenshot credits` | Shows the credits left on your account and its limits. |
| `localscreenshot login` | Saves your key on this machine. |
| `localscreenshot logout` | Removes the saved key. |

`countries` and `credits` take `--json` too.

## From Python

The Python package is also a library. `screenshot()` takes the same options as the command and returns the image.

**From Python**

```python
from localscreenshot import screenshot

shot = screenshot("https://example.com", country="BR", full_page=True)
with open(f"example.{shot.extension}", "wb") as file:
    file.write(shot.image)

print(shot.width, shot.height, shot.credits_charged, shot.credits_remaining)
```

Its arguments are `country`, `full_page`, `device`, `format`, `click_text`, `block_cookie_banners`, `block_ads` and `dark`. It reads the key from `LOCALSCREENSHOT_API_KEY` or from the file written by `login`, or takes `api_key=`. When the API refuses or the screenshot fails, it raises `localscreenshot.ApiError`, which carries the error `code` of the API.

## When it fails

The command prints one line on the error output and exits with a code a script can test.

| Exit code | What happened |
| --- | --- |
| `0` | Done. The image is saved. |
| `1` | The API refused the request, or the screenshot failed. The line reads `Error <code>: <message>`, with a code from the [Errors](https://docs.localscreenshot.com/errors) page. |
| `2` | The command was not used correctly: no key, an unknown option, or something that is neither a command nor a web address (`http://` or `https://`). Nothing was sent. |
| `130` | You stopped it with Ctrl+C. |

An output path that cannot be written (the file exists, it is a folder, its folder is missing) also ends with `2`, before any request. One rare case comes after the request: without `-o`, the name is built from the site and the time, and if a file of that name appears while the screenshot is being taken, the image is not written. You still find it in your dashboard.

At the `login` prompt, the Node package exits with `2` on Ctrl+C, not `130`.

The command waits up to three minutes for a screenshot. After that it stops with `still_running` and gives you the id: the screenshot still finishes, and you find it in your dashboard.

## What it costs

- A screenshot uses 1 credit. From a chosen country, it uses 2.
- A failed screenshot is not charged.
- `localscreenshot credits` shows what is left. The rules are on [Credits and limits](https://docs.localscreenshot.com/credits).

## Your key stays with you

- The key goes to the API host only, over HTTPS. Redirects are not followed.
- The image is downloaded through its signed link, without the key.
- No message ever prints the key.

## Packages and source

The Python package is on PyPI: [https://pypi.org/project/localscreenshot/](https://pypi.org/project/localscreenshot/).

The Node package is on npm: [https://www.npmjs.com/package/localscreenshot](https://www.npmjs.com/package/localscreenshot). Both packages offer the same command, with the same options.

The source code is public, under the MIT license: [https://github.com/Sambel/localscreenshot-cli](https://github.com/Sambel/localscreenshot-cli).

> **What it does not do.** Like the API, it does not sign in to websites, solve CAPTCHAs or get past paywalls. You get a clear error instead.
