> ## Documentation Index
> Fetch the complete documentation index at: https://docs.perplexity.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Perplexity CLI

> Install and use Perplexity's pplx command-line interface for web search and page-content retrieval from your terminal or coding agent.

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 readable page content.

## 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).
Choose one authentication method:

<Tabs>
  <Tab title="Environment variable">
    ```bash theme={null}
    export PERPLEXITY_API_KEY="your_api_key_here"
    ```
  </Tab>

  <Tab title="Interactive login">
    ```bash theme={null}
    pplx auth login
    ```
  </Tab>
</Tabs>

## 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."
        }
      }
    ]
  }
  ```
</Accordion>

<Info>
  `-n` defaults to `10`.
  Run `pplx search web --help` for the full flag list and a summary of the input and output shapes.
</Info>

### Filter results

These flags scope a search.
They are the Search API filters, so their behavior and limits are identical — see [domain filter](/docs/search/filters/domain-filter) and [date and time filters](/docs/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`                            |

<Note>
  `--recency-filter` cannot be combined with `--published-after-date` or `--published-before-date`.
  That request fails with `BAD_REQUEST`.
</Note>

### 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).

## Fetch page content

Retrieve cleaned text and page metadata from an HTTP or HTTPS URL:

```bash theme={null}
pplx content fetch https://docs.perplexity.ai/docs/getting-started/overview
```

<Accordion title="Response">
  ```json wrap theme={null}
  {
    "url": "https://docs.perplexity.ai/docs/getting-started/overview",
    "title": "Overview - Perplexity",
    "description": null,
    "authors": [],
    "published_date": null,
    "domain": "perplexity",
    "is_paywall": false,
    "is_cached": true,
    "content": "> ## Documentation Index\n> Fetch the complete documentation index at: https://docs.perplexity.ai/llms.txt ...",
    "error": null
  }
  ```
</Accordion>

### Serve from cache or crawl live

Fetches serve cached content by default, which is the fast and dependable path.
`is_cached` in the response tells you which one you got.

`--no-cache` forces a live crawl of the origin instead:

```bash theme={null}
pplx content fetch https://www.iana.org/help/example-domains --no-cache
```

The response has the same shape, with `is_cached` set to `false`.
Expect a live crawl to fail on a fair share of pages, though: a slow origin or a `robots.txt` that disallows crawling comes back as a populated `error` and an empty `content`, where the cached path would have returned the text.
Reach for `--no-cache` only when you specifically need to bypass the cache.

### Get the raw page source

`--html` returns the unprocessed page source in a `raw_html` field, for the cases where you need markup that the cleaner drops:

```bash theme={null}
pplx content fetch https://docs.perplexity.ai/docs/getting-started/overview --html
```

This flag also crawls live, so it carries the same failure modes as `--no-cache`, and the cleaned `content` comes back empty — you get `raw_html` instead of `content`, not in addition to it.

### Keep large pages out of stdout

A single page is routinely tens of thousands of characters.
`--output-dir` writes the full response under `<dir>/fetch/`, and `--stdout-preview` truncates the long strings on stdout:

```bash theme={null}
pplx content fetch https://docs.perplexity.ai/docs/getting-started/overview \
  --output-dir pages \
  --stdout-preview=200
```

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

### Detect paywalled pages

`is_paywall` is `true` when the page sits behind a paywall or a login.
Only the fragment above the wall could be extracted, so `content` is real text but not the whole page.
Check it before you treat a fetch as complete.

### Fetch errors

`pplx content fetch` does not fail the way the other commands do.
When the origin refuses the request or times out, the command still writes its normal JSON object to stdout: `content` comes back empty and `error` holds a message string.

```bash theme={null}
pplx content fetch https://www.example.com/example/
```

<Accordion title="Response">
  ```json wrap theme={null}
  {
    "url": "https://www.example.com/example/",
    "title": null,
    "description": null,
    "authors": [],
    "published_date": null,
    "domain": null,
    "is_paywall": false,
    "is_cached": false,
    "content": null,
    "error": "Page not found or unavailable: http_code_client_error. Try another tool."
  }
  ```
</Accordion>

Check `error` on every fetch, because a successful invocation does not mean you got a page.

## 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                                                          |
</Accordion>

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.
