# Perplexity CLI

The `pplx` CLI returns structured JSON from the Perplexity Search API, making it useful for shell pipelines, interactive terminal work, and coding agents that need current web results or query-relevant page snippets.

## Install

Open the agent in your project and send it this:

```text wrap theme={null}
Read https://github.com/perplexityai/api-platform-developers/blob/main/skills/pplx-cli/SKILL.md and install this skill, then use it to search the web from my terminal.
```

Without an agent, run the installer yourself:

```bash theme={null}
curl -fsSL https://github.com/perplexityai/perplexity-cli/releases/latest/download/install.sh | sh
```

## Authenticate

Every command needs a [Perplexity API key](https://console.perplexity.ai/project/keys).
Choose one authentication method:

::::tabs
:::tab{title="Environment variable"}
```bash theme={null}
export PERPLEXITY_API_KEY="your_api_key_here"
```
:::

:::tab{title="Interactive login"}
```bash theme={null}
pplx auth login
```
:::
::::

## Search the web

```bash theme={null}
pplx search web "what is a bloom filter" -n 2
```

:::accordion{title="Response"}
```json wrap theme={null}
{
  "total": 2,
  "hits": [
    {
      "url": "https://en.wikipedia.org/wiki/Bloom_filter",
      "title": "Bloom filter",
      "domain": "en.wikipedia.org",
      "snippet": "In computing, a **Bloom filter** is a space-efficient probabilistic data structure, conceived by Burton Howard ...",
      "summary": "In computing, a **Bloom filter** is a space-efficient probabilistic data structure, conceived by Burton Howard ...",
      "date": "2004-04-17",
      "last_updated": "2026-07-08",
      "trust": {
        "level": 2,
        "name": "trusted",
        "description": "is trusted for community-edited general knowledge and reference articles across education, science, history, and many non-controversial topics worldwide."
      }
    },
    {
      "url": "https://systemdesign.one/bloom-filters-explained/",
      "title": "Bloom Filters Explained - System Design",
      "domain": "systemdesign.one",
      "snippet": "## What is a bloom filter?\nA Bloom filter is a space-efficient probabilistic data structure that is used to te ...",
      "summary": "## What is a bloom filter?\nA Bloom filter is a space-efficient probabilistic data structure that is used to te ...",
      "date": "2023-03-06",
      "last_updated": "2026-07-13",
      "trust": {
        "level": 1,
        "name": "credible",
        "description": "is credible for personally authored software system design case studies and interview preparation content without formal institutional peer review."
      }
    }
  ]
}
```
:::

:::callout{intent="info"}
`-n` defaults to `10`.
Run `pplx search web --help` for the full flag list and a summary of the input and output shapes.
:::

### Filter results

These flags scope a search.
They are the Search API filters, so their behavior and limits are identical — see [domain filter](/guides/agent-api-search-filters-domain-filter) and [date and time filters](/guides/agent-api-search-filters-date-time-filters) for the details.

```bash theme={null}
pplx search web "AI inference hardware" \
  --domains arxiv.org,nvidia.com \
  --published-after-date 07/01/2026 \
  -n 5
```

| Flag                      | Format                                 | Description                                 | Example                                   |
| ------------------------- | -------------------------------------- | ------------------------------------------- | ----------------------------------------- |
| `--domains`               | Comma-separated hostnames              | Return results only from these domains      | `--domains arxiv.org,nvidia.com`          |
| `--excluded-domains`      | Comma-separated hostnames              | Drop results from these domains             | `--excluded-domains reddit.com,quora.com` |
| `--published-after-date`  | `MM/DD/YYYY`                           | Published on or after this date             | `--published-after-date 07/01/2026`       |
| `--published-before-date` | `MM/DD/YYYY`                           | Published on or before this date            | `--published-before-date 07/31/2026`      |
| `--updated-after-date`    | `MM/DD/YYYY`                           | Last modified on or after this date         | `--updated-after-date 07/01/2026`         |
| `--updated-before-date`   | `MM/DD/YYYY`                           | Last modified on or before this date        | `--updated-before-date 07/31/2026`        |
| `--recency-filter`        | `hour`, `day`, `week`, `month`, `year` | Relative window instead of explicit dates   | `--recency-filter week`                   |
| `--country`               | ISO 3166-1 alpha-2 code                | Region the search runs for, `US` by default | `--country DE`                            |

:::callout{intent="note"}
`--recency-filter` cannot be combined with `--published-after-date` or `--published-before-date`.
That request fails with `BAD_REQUEST`.
:::

### Ask the same question several ways

Extra positional queries are rephrasings of one question, not separate searches.
The CLI still returns a single ranked result set, but wording the question more than one way surfaces pages that only match the phrasing you did not think of first:

```bash theme={null}
pplx search web \
  "kubernetes pod OOMKilled causes" \
  "why does k8s keep killing my pod with OOMKilled"
```

### Save full results

Save the complete result while keeping stdout small:

```bash theme={null}
pplx search web "kubernetes pod OOMKilled causes" \
  --output-dir out \
  --stdout-preview=200
```

The full response is written under `out/web/`, and stdout includes its path in `saved_to`.
`--stdout-preview` only truncates stdout when you also set `--output-dir` or `PPLX_OUTPUT_DIR`.
Cut strings end in `...<truncated>` and the response gains a top-level `"truncated": true`.

### Search errors

A search either succeeds or fails outright: on failure nothing reaches stdout and the JSON error object goes to stderr.
The search-specific code is `BAD_REQUEST`, which the service returns when the filters contradict each other, as with `--recency-filter` alongside a publication-date bound.
Everything else you can hit here is a [common error](#handle-errors).

## Generate query-relevant snippets

Extract the passages of a page that are relevant to a query, instead of retrieving the whole page:

```bash theme={null}
pplx content snippets "how does a bloom filter decide set membership" \
  https://en.wikipedia.org/wiki/Bloom_filter
```

:::accordion{title="Response"}
```json wrap theme={null}
{
  "results": [
    {
      "url": "https://en.wikipedia.org/wiki/Bloom_filter",
      "text": "In computing, a **Bloom filter** is a space-efficient probabilistic data structure, conceived by Burton Howard Bloom in 1970, that is used to test whether an element is a member of a set. False positive matches are possible, but false negatives are not ...",
      "tokens_count": 1047
    }
  ]
}
```
:::

`text` keeps only the query-relevant passages of the page; elided regions in between are marked with the `…` character.

:::callout{intent="info"}
`content snippets` requires CLI v0.2.3 or later.
On an older binary, run `pplx update` first.
:::

:::callout{intent="note"}
`pplx content fetch` is deprecated and will stop working; use `content snippets`.
:::

### Cover several pages in one call

Extra positional URLs are additional pages, not rephrasings: unlike `pplx search web`, where extra positional arguments reword one question, each URL here is snipped independently against the same query.
One call takes up to 50 URLs:

```bash theme={null}
pplx content snippets "bloom filter false positive rate" \
  https://en.wikipedia.org/wiki/Bloom_filter \
  https://systemdesign.one/bloom-filters-explained/ \
  --max-tokens-per-page 256
```

:::accordion{title="Response"}
```json wrap theme={null}
{
  "results": [
    {
      "url": "https://en.wikipedia.org/wiki/Bloom_filter",
      "text": "More generally, fewer than 10 bits per element are required for a 1% false positive probability, independent of the size or number of elements in the set.\n\n…\n\nIf all are 1, then either the element is in the set, *or* the bits have by chance been set to 1 during the insertion of other elements, resulting in a false positive. ...",
      "tokens_count": 261
    },
    {
      "url": "https://systemdesign.one/bloom-filters-explained/",
      "text": "### Bloom filter false positive\n\nIn Figure 5, the bloom filter is queried to check the membership of item *green*, which is not a member of the bloom filter. ...",
      "tokens_count": 262
    }
  ]
}
```
:::

### Budget the tokens

Two flags cap how much text comes back.

| Flag                    | Range       | Default                 | Description                                                                  |
| ----------------------- | ----------- | ----------------------- | ---------------------------------------------------------------------------- |
| `--max-tokens`          | `1`–`16384` | `4096`                  | Maximum total tokens across all snippets                                     |
| `--max-tokens-per-page` | `1`–`4096`  | `min(1024, max_tokens)` | Maximum tokens for any single page's snippet; must not exceed `--max-tokens` |

Budgets are approximate: a snippet can run a few tokens over its cap, as the `tokens_count` values above show.

### Snippet errors

`pplx content snippets` reports failure per URL, not per command.
A page that cannot be snipped does not fail the run: the command still exits `0`, and that URL's result carries an `error` message with no `text`.

```bash theme={null}
pplx content snippets "example domain reserved documentation" \
  https://www.iana.org/help/example-domains \
  https://www.example.com/nonexistent/
```

:::accordion{title="Response"}
```json wrap theme={null}
{
  "results": [
    {
      "url": "https://www.iana.org/help/example-domains",
      "text": "1. Instructions and Guides\n\n# Example Domains\n\nAs described in RFC 2606 and RFC 6761, a number of domains such as example.com and example.org are maintained for documentation purposes. ...",
      "tokens_count": 152
    },
    {
      "url": "https://www.example.com/nonexistent/",
      "error": "no snippet could be generated under the requested token budget"
    }
  ]
}
```
:::

Check every result for `error` before trusting its `text`, because a successful invocation does not mean every page produced a snippet.

### Keep large responses out of stdout

Snippets across many URLs still add up.
`--output-dir` writes the full response under `<dir>/snippets/`, and `--stdout-preview` truncates the long strings on stdout:

```bash theme={null}
pplx content snippets "how does a bloom filter decide set membership" \
  https://en.wikipedia.org/wiki/Bloom_filter \
  --output-dir out \
  --stdout-preview=200
```

:::accordion{title="Response"}
```json wrap theme={null}
{
  "results": [
    {
      "url": "https://en.wikipedia.org/wiki/Bloom_filter",
      "text": "In computing, a **Bloom filter** is a space-efficient probabilistic data structure, conceived by Burton Howard Bloom in 1970, that is used to test whether an element is a member of a set. False positi...<truncated>",
      "tokens_count": 1047
    }
  ],
  "saved_to": "out/snippets/c6989ad7.json",
  "truncated": true
}
```
:::

Stdout carries the saved path in `saved_to` plus `"truncated": true`, so the terminal stays readable while the complete text sits on disk.

## Handle errors

These are the failures common to every `pplx` command.
A failed command writes one JSON error object to stderr:

```json theme={null}
{
  "error": {
    "code": "AUTHENTICATION",
    "message": "...",
    "command": "search.web",
    "hint": "Set the PERPLEXITY_API_KEY environment variable"
  }
}
```

Branch on `error.code`.

:::accordion{title="Error codes"}
| Code                                         | Raised when                                                                                 |
| -------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `AUTHENTICATION`                             | No key is configured, or the key is invalid                                                 |
| `FORBIDDEN`                                  | The key does not have access to what you requested                                          |
| `RATE_LIMIT`                                 | You are over your rate limit                                                                |
| `BAD_REQUEST`                                | The service rejected the request, for example `--recency-filter` combined with a date bound |
| `VALIDATION`                                 | The service rejected a field value                                                          |
| `NOT_FOUND`                                  | The requested resource does not exist                                                       |
| `TIMEOUT`                                    | The request took too long                                                                   |
| `CONNECT`                                    | The CLI could not reach the API                                                             |
| `INTERNAL_SERVER`                            | The service failed                                                                          |
| `UNKNOWN_ARGUMENT`                           | The flag does not exist on this command                                                     |
| `INVALID_VALUE`, `VALUE_VALIDATION`          | A flag value is malformed or out of range                                                   |
| `MISSING_REQUIRED_ARGUMENT`, `MISSING_QUERY` | A required argument or the query is missing                                                 |
| `ARGUMENT_ERROR`                             | Any other argument-parsing failure                                                          |
:::

Run `pplx <command> --help` before assuming that a flag exists; CLI output is already JSON, so no `--json` flag is needed.

## Next steps

See the [`perplexity-cli` repository](https://github.com/perplexityai/perplexity-cli) for release notes, manual installation, and uninstall instructions.

## Related pages

- [Admin & Management](./admin-management-index.md)
- [Agent API](./agent-api-2-index.md)
- [Agent API](./agent-api-index.md)
- [Analytics API](./analytics-api-index.md)
- [Authentication](./authentication-index.md)
- [Changelog](../changelog.md)
- [Cookbook](./cookbook-2-index.md)
- [Embeddings API](./embeddings-api-2-index.md)
- [Embeddings API](./embeddings-api-index.md)
- [Getting Started](./getting-started-index.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
