# LinkedIn CLI

AI-agent-friendly CLI for LinkedIn automation. Install, set up, and start using in under 2 minutes.

LinkedIn CLI gives AI agents and developers full LinkedIn capabilities through simple shell commands. Built for Claude Code, Cursor, Codex, and any AI agent that can execute shell commands.

> Source code available on [GitHub](https://github.com/Linked-API/linkedin-cli).

## Quick start

```bash
# 1. Install
npm install -g @linkedapi/linkedin-cli

# 2. Save your tokens (get them at app.linkedapi.io)
linkedin setup

# 3. Fetch a profile
linkedin person fetch https://www.linkedin.com/in/vprudnikoff --json

# 4. Search for people
linkedin person search --term "revops engineer" --current-companies "Linked API" --json

# 5. Send a message
linkedin message send https://www.linkedin.com/in/vprudnikoff "Hey, loved your latest post!"
```

## Install

```bash
npm install -g @linkedapi/linkedin-cli
```

## Setup

```bash
linkedin setup
```

The CLI will ask for your **Linked API Token** and **Identification Token**. Get them at [app.linkedapi.io](https://app.linkedapi.io).

For non-interactive environments (CI, scripts):

```bash
linkedin setup --linked-api-token=xxx --identification-token=yyy
```

| Flag | Description |
| --- | --- |
| `--linked-api-token` | Linked API Token (skips prompt) |
| `--identification-token` | Identification Token (skips prompt) |

## Multiple accounts

Run `linkedin setup` again with different tokens to add more accounts. The last added account becomes active.

```bash
# List all accounts (* marks active)
linkedin account list

# Switch active account
linkedin account switch "Vlad"

# Update tokens for active account (e.g. after regenerating tokens on the dashboard)
linkedin account update

# Update tokens for a specific account
linkedin account update "Vlad"

# Rename a saved account
linkedin account rename "Vlad" --name "My Work Account"

# Use a specific account for one command
linkedin person fetch https://www.linkedin.com/in/... --account "Vlad"

# Remove active account (auto-switches to next)
linkedin reset

# Remove all accounts
linkedin reset --all
```

## Updating tokens

If your tokens were regenerated on the [dashboard](https://app.linkedapi.io), update them in the CLI without removing the account:

```bash
linkedin account update
```

This prompts for new tokens, verifies them, and updates the saved account in place. To update a specific account:

```bash
linkedin account update "Account Name"
```

For non-interactive environments:

```bash
linkedin account update --linked-api-token=xxx --identification-token=yyy
```

| Flag | Description |
| --- | --- |
| `--linked-api-token` | New Linked API Token (skips prompt) |
| `--identification-token` | New Identification Token (skips prompt) |

## How it works

Under the hood, [Linked API](https://linkedapi.io) runs a dedicated cloud browser instance for each connected LinkedIn account. When a command is executed, the CLI sends the request to Linked API's infrastructure, where an isolated browser with a residential IP performs the action on LinkedIn – simulating human-like mouse movements, keyboard input, and natural browsing patterns. No local browsers, no proxies, no Selenium, no infrastructure to manage. [Learn more about safety](/safety).

## Global flags

Every command supports these flags:

| Flag | Description |
| --- | --- |
| `--json` | Structured JSON output to stdout |
| `--fields name,url,...` | Select specific fields in output |
| `--quiet` / `-q` | Suppress stderr progress |
| `--no-color` | Disable colors |
| `--account "Name"` | Use a specific account for this command |

## Output format

**JSON mode** (`--json` or non-TTY stdout):

```json
{"success": true, "data": {"name": "Vlad Prudnikov", "headline": "CEO at Linked API"}}
```

```json
{"success": false, "error": {"type": "personNotFound", "message": "Person not found"}}
```

**Human mode** (TTY stdout): key-value pairs for objects, tables for arrays.

## Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Success (check `success` field – action may have returned an error like "person not found") |
| `1` | General/unexpected error |
| `2` | Missing or invalid tokens |
| `3` | Subscription/plan required |
| `4` | LinkedIn account issue |
| `5` | Invalid arguments |
| `6` | Rate limited |
| `7` | Network error |
| `8` | Workflow timeout (workflowId returned for recovery) |

## Important notes

- **Sequential execution.** Linked API executes all workflows sequentially per account. You can send multiple requests, but they queue and run one at a time.
- **Not instant.** Simple operations (fetch a profile) take ~10-20 seconds. Complex operations (search with filters) can take longer. This is because a real cloud browser navigates LinkedIn on your behalf.
- **Timestamps in UTC.** All dates and times returned by the API are in UTC.
- **URL normalization.** All LinkedIn URLs in responses are normalized to `https://www.linkedin.com/...` format without trailing slashes.
- **Null fields.** Fields that are unavailable are returned as `null` or `[]`, not omitted.
- **Action limits.** Configurable per-account action limits on the [platform](https://app.linkedapi.io) prevent LinkedIn policy violations. When a limit is reached, you get a `limitExceeded` error.
- **Admin commands.** Manage your subscription, accounts, and limits with `linkedin admin`. See [Administration](/cli/administration).
- **Webhooks.** Receive workflow and account events on your own endpoint instead of polling. See [Webhook Events](/docs/webhooks).
