@lucasygu/lockedout
v0.3.3
Published
Node CLI for LinkedIn — read profiles, posts, companies, jobs, and search via a stealth browser session.
Downloads
466
Maintainers
Readme
lockedout — LinkedIn from the command line
Node CLI for reading LinkedIn profiles via a persistent stealth Chromium session. Built on Patchright. No API keys, no cookie copying — just lockedout login once, then scrape from your terminal.
Easiest way to get started
Paste this to your AI agent (Claude Code, Cursor, Codex, Windsurf, OpenClaw, etc.):
"Install the
@lucasygu/lockedoutLinkedIn CLI tool via npm. Then runlockedout loginto sign in once, andlockedout statusto verify. Repo: https://github.com/lucasygu/lockedout"The agent will install the CLI, walk you through the one-time browser sign-in, and verify the session. After that, try: "Pull this person's LinkedIn profile and summarize their career trajectory" — the agent will run
lockedout profile <slug> --json, parse the sections, and produce a structured summary.
Install
npm install -g @lucasygu/lockedoutRequires Node.js >= 22. Supports macOS, Linux, Windows.
First run note. The first
lockedout logindownloads ~150 MB of Chromium into the shared Patchright/Playwright cache (~/Library/Caches/ms-playwright/on macOS,~/.cache/ms-playwright/on Linux). It's a one-time cost — subsequent runs are instant. Already have Playwright installed? It'll be a no-op; we share the cache.
After installing, run lockedout login to sign in (2FA / captcha OK). The CLI persists your session at ~/.lockedout/profile/ so you don't have to log in again until LinkedIn flags it.
Why this exists
Cookie-only LinkedIn tools (@bcharleson/linkedincli, tomquirk/linkedin-api) get sessions revoked within 1–2 calls. LinkedIn's BrowserGate / APFC fingerprint header is generated by ~2.7 MB of JS that has to run in a real browser — you can't fake it, copy it, or replay it. The only architecture that works in 2026 is "be a real browser." That's what lockedout is.
What you can do
- Profile read — pull anyone's LinkedIn profile sections (experience, education, skills, etc.) as structured JSON
- Session-aware scraping — uses your real LinkedIn session via a stealth Chromium profile; no API keys
- Built-in safety — jittered delays defeat LinkedIn's "heartbeat" detection, daily quotas cap your exposure, automatic cooldown engages on rate-limit signals
- AI-agent-first — auto-installs as a Claude Code skill (
/lockedout); JSON output is designed for LLM parsing
Quick start
# One-time browser sign-in (downloads Chromium on first run)
lockedout login
# Verify the session is alive
lockedout status
# Read a profile (defaults to main_profile section only)
lockedout profile satyanadella --json
# Read multiple sections
lockedout profile satyanadella --sections experience,education,skills --json
# See today's quota usage
lockedout usage
# When something breaks — run this first
lockedout doctor
# Check / clear cooldown
lockedout cooldown status
lockedout cooldown clearCommands
| Command | Description |
|---|---|
| login | Open Chromium, sign in to LinkedIn manually. Cookies persist to ~/.lockedout/profile/. |
| status | Headless probe that checks if the saved session is still valid. |
| logout | Wipe the local session (rm -rf ~/.lockedout/). |
| profile <username> | Scrape a person profile. Accepts a slug (satyanadella) or full URL. |
| doctor | End-to-end self-diagnostic — run this first when something breaks. Supports --json and --quick. |
| usage | Show today's scrape count, daily cap, and cooldown status. |
| cooldown status | Show remaining cooldown time. |
| cooldown clear | Clear an active cooldown (use only if you're confident it was overcautious). |
Profile options
| Option | Description | Default |
|---|---|---|
| --sections <list> | Comma-separated sections to fetch | main_profile only |
| --max-scrolls <n> | Max scroll attempts per section page | 5 |
| --json | JSON output | false |
| --pretty | Human-readable text | true |
| --force | Bypass the daily quota cap | false |
Available sections: main_profile, experience, education, interests, honors, languages, certifications, skills, projects, posts.
⚠️ Rate-limit safety. LinkedIn detects automation behaviorally — uniform delays between actions are the #1 signal. lockedout jitters every wait (1.5–3.5s nav, 0.3–0.8s scroll), caps actions at 40/day (50 in the first 14 days post-install), and auto-engages a 30-min cooldown on any rate-limit or auth signal. Override with
--forceonly when you accept the risk. Industry data: ~23% of LinkedIn automation users hit account restrictions within 90 days; these guards are designed to keep you out of that bucket.
Troubleshooting
Always start with: lockedout doctor (or lockedout doctor --json for tooling). It runs 8 checks across Node, Patchright, Chromium, profile, session, quota, cooldown, and the skill symlink — most "doesn't work" reports resolve at this step. If doctor is green and a scrape still fails, the problem is on LinkedIn's side, not the skill.
| Problem | Solution |
|---|---|
| Anything unexpected — start here | lockedout doctor |
| Auth: LinkedIn requires interactive re-authentication | Run lockedout login. A 30-min cooldown will auto-engage; lockedout cooldown clear after re-login if you want to scrape immediately. |
| Cooldown active: N min remaining | Wait it out, or lockedout cooldown clear if the trigger was a known false positive. |
| Daily cap reached: N/N. Resets in ~Xh | Wait for UTC reset, or use --force for one more scrape if needed. |
| Setting up Chromium (one-time, ~150 MB)... | Normal first-run download — wait for it to complete. |
| Chromium install failed (exit N) | Run npx patchright install chromium manually to see the underlying error. |
| lockedout profile returns mostly empty sections | Likely a soft rate-limit on that account. Check lockedout cooldown status. If clean, wait an hour and retry. |
| Skills section returns just headers | Known v0.3.0 limitation — LinkedIn's new skills UI needs a "Show all" tab click that's not yet implemented. |
| lockedout status returns logged_in: false | Session expired or LinkedIn rotated cookies. Run lockedout login again. |
How it works
| Layer | What we use | Why |
|---|---|---|
| Browser | Patchright — stealth-patched Playwright fork | Removes --enable-automation, adds --disable-blink-features=AutomationControlled, blocks Runtime.enable / Console.enable leaks. Necessary but not sufficient — see below. |
| Session | Persistent Chromium profile at ~/.lockedout/profile/ | LinkedIn's own JS generates lidc, bcookie, bscookie, liap, and the APFC fingerprint header; we don't fake any of it. |
| Chromium | Lazy-downloaded on first login | We don't bundle (npm has a 250 MB hard cap; Chromium is 280 MB). We don't postinstall-download (slow, hostile UX). First login triggers npx patchright install chromium; subsequent runs reuse the shared cache. |
| Extraction | innerText from rendered DOM, not CSS selectors | Resilient to LinkedIn's frequent UI churn. The output is loosely structured text per section, ideal for LLM downstream parsing. |
| Anti-detection | Jitter + daily quota + cooldown | Static fingerprint defeat (Patchright) is necessary but doesn't address behavioral patterns. lockedout adds randomized delays, a 40/day cap, and auto-engaged cooldowns. See docs/rate-limiting.md. |
AI agent integration
Claude Code
Auto-registers as a skill at install time via the postinstall hook (which symlinks ~/.claude/skills/lockedout to the npm package). After npm install -g @lucasygu/lockedout, the /lockedout slash command is available immediately.
Use the slash command directly:
/lockedout profile satyanadella
/lockedout status
/lockedout usageOr give Claude Code natural-language tasks:
- "Pull Satya Nadella's career history from LinkedIn and summarize the timeline"
- "Compare these three profiles' education sections"
- "Check today's scrape budget before starting batch lookups"
- "Walk me through the first-time login flow"
Claude Code combines multiple commands, parses the JSON, and produces structured analysis — driven by the SKILL.md instructions inside the package.
Acknowledgments
- stickerdaniel/linkedin-mcp-server (Apache-2.0) — the Python MCP server we ported to Node/TypeScript. The innerText-extraction strategy, the auth-barrier and rate-limit detection, the persistent-profile design — all credit to the upstream maintainers.
- Patchright by Kaliiiiiiiiii-Vinyzu — the stealth-patched Playwright fork that makes any of this possible. Maintained as the modern replacement for the (dead since 2023)
puppeteer-extra-stealth.
Disclaimer
LinkedIn's Terms of Service prohibit automated access to the platform. Per 2025–2026 industry data (Salesflow, Salesloop, Connectsafely.ai, others), approximately 23% of users running LinkedIn automation tools hit an account restriction within 90 days. lockedout adds jittered delays, daily quotas, and an automatic cooldown circuit-breaker to reduce that risk, but cannot eliminate it.
Use responsibly:
- One personal account per machine. Do not use lockedout on accounts you can't afford to lose.
- Read
docs/rate-limiting.mdbefore any bulk operation. - This project is not affiliated with LinkedIn.
License
MIT © 2026 Lucas Gu
