Browser

Tinker LinkedIn

Try it

Your agent crawls LinkedIn through the browser session you already have — profiles, search, connections, inbox, feed. No official API, no app review. Your cookies never leave the browser: API calls are a fetch() run inside the linkedin.com tab you shared (people-search navigates that tab to a LinkedIn search page and reads the results), and 1.2.1 DELETED the cookie-extraction, session-store and external-replay code from the package rather than leaving it switched off — there is no longer anything to store or steal. Every request, navigation and tab pick is pinned to exactly https://www.linkedin.com, including the LINKEDIN_TARGET_ID override, so a look-alike host cannot borrow your session. Reads and drafts freely; the one write, message-send, needs per-action consent that repeats the exact conversation URN, and without it you get the draft and nothing is sent. The browser relay must be a literal loopback IP, with no override. Daily ceilings count every record requested and are reserved

What it does

One of dozens of skills and plugins in **TinkerClaw** — a self-improving OpenClaw fork that's been running 24/7 for months.

The skill document

One of dozens of skills and plugins in TinkerClaw — a self-improving OpenClaw fork that's been running 24/7 for months.

No official LinkedIn API. No app review. No OAuth dance that dies in 60 days.

LinkedIn's product surface is a private REST API called Voyager. The website already talks to it with cookies from your signed-in browser. This skill does the same thing: share a linkedin.com tab, extract the session once, then crawl profiles / people search / companies / connections / inbox / feed from a zero-dep Node CLI.

Part of TinkerClaw — real-time token tracking, self-improving crons, persistent cognitive memory.

👉 https://github.com/globalcaos/tinkerclaw

Clone it. Fork it. Break it. Make it yours.

LinkedIn Hack

LinkedIn bans automation that looks like a bot farm. This skill is deliberately boring: soft daily ceilings, send gated behind an explicit flag, the session cookie sealed in your OS keychain, and the same "borrow the browser session" pattern as teams-hack / factorial-hack. Useful for research and inbox triage — not for spray-and-pray outreach.

  • Crawl through a shared LinkedIn tab (browser transport — default). Cookies stay in-browser.
  • Identity: me, profile via Voyager in-tab fetch
  • People search via search-results page DOM scrape (LinkedIn SDUI broke classic Voyager search)
  • Company/profile/connections/inbox/feed: Voyager in-tab (best-effort where endpoints still live)
  • Optional external cookie-jar transport (LINKEDIN_TRANSPORT=external) — fragile; often burns li_at
  • Optional message send (hard-gated: requires --i-mean-it)
  • Daily activity counters with soft rate limits + request pacing
  • Session sealed in the OS keychain (secret-tool / security), with a warned 0600 file fallback
  • One-command off switch: session logout [--purge-data]

Quick Start

0. Relay Preflight — DO THIS FIRST

Extraction runs through the OpenClaw browser relay, which only exposes tabs the user actively clicked Share on. Empty tab list ≠ broken code.

  1. Confirm relay is up: GET http://127.0.0.1:/extension/statusconnected:true, count>=1 (`` = browser.profiles.chrome-relay.cdpUrl in ~/.openclaw/openclaw.json, usually 18792)
  2. List tabs (GET /tabs or browser action=tabs) and confirm a linkedin.com tab is shared. Grab its targetId.

If count is 0 or LinkedIn isn't listed: reload the OpenClaw extension (chrome://extensions) in the browser holding LinkedIn, click Share on the tab, re-check.

1. Session Extraction (one-time, ~30 seconds)

Open https://www.linkedin.com/feed/ while signed in. Share the tab via the OpenClaw extension.

Default transport is in-tab (LINKEDIN_TRANSPORT=browser). No cookie extract required for crawl — share a feed tab and call commands, and the cookies never leave the browser.

Persisting the session is opt-in: without --store, extract-cdp only reports which cookies it can see (names and lengths, never values). Pass --store and the session is sealed in your OS keychain — or, if you have no keychain, written to a 0600 file with a warning:

node {baseDir}/scripts/linkedin.mjs session extract-cdp --store
node {baseDir}/scripts/linkedin.mjs session status    # says where it landed
node {baseDir}/scripts/linkedin.mjs session logout    # erases it from both stores

Do not use external cookie replay as the main path. Live 2026-07-29: external /me after extract worked once, then every further external call 302'd and the browser lost li_at (login wall). In-tab fetch does not burn the session the same way.

Do not burst. Pace is built in (LINKEDIN_PACE_MS, default 1200). One command at a time after login.

B. Fallback — evaluate in page (usually misses httpOnly li_at):

(() => {
  const want = ['li_at', 'JSESSIONID', 'bcookie', 'bscookie', 'li_a', 'lidc', 'liap'];
  const cookies = {};
  for (const part of document.cookie.split(';').map(s => s.trim()).filter(Boolean)) {
    const eq = part.indexOf('=');
    if (eq < 0) continue;
    const k = part.slice(0, eq);
    if (want.includes(k)) cookies[k] = part.slice(eq + 1);
  }
  return {
    cookies,
    csrf: cookies.JSESSIONID?.replace(/^"|"$/g, '') || null,
    has_li_at: Boolean(cookies.li_at),
    note: cookies.li_at ? 'ok' : 'li_at httpOnly — use browser cookies action',
  };
})();

Store (never echo li_at into chat history if you can avoid it):

node {baseDir}/scripts/linkedin.mjs session store \
  --li-at '' \
  --jsessionid '' \
  --bcookie '' \
  --bscookie ''

csrf-token defaults to the unquoted JSESSIONID (Voyager's usual rule).

2. Verify

node {baseDir}/scripts/linkedin.mjs session test
node {baseDir}/scripts/linkedin.mjs me

3. Crawl

node {baseDir}/scripts/linkedin.mjs search people "warehouse director spain" --top 10
node {baseDir}/scripts/linkedin.mjs profile some-vanity-slug
node {baseDir}/scripts/linkedin.mjs company microsoft
node {baseDir}/scripts/linkedin.mjs connections --top 40
node {baseDir}/scripts/linkedin.mjs conversations --top 15
node {baseDir}/scripts/linkedin.mjs messages 'urn:li:msg_conversation:(…)' --top 30
node {baseDir}/scripts/linkedin.mjs feed --top 10
node {baseDir}/scripts/linkedin.mjs activity show

How It Works

  1. LinkedIn web uses cookies (li_at session + JSESSIONID / CSRF) for Voyager.
  2. The skill seals those cookies in your OS keychain (secret-tool on Linux, security on macOS, entry openclaw-linkedin-hack/linkedin-session). With no keychain present it falls back to ~/.openclaw/credentials/linkedin-session.json at mode 0600 and prints a warning every time it writes. Only one copy is ever kept: a successful keychain write deletes the file.
  3. CLI replays them against https://www.linkedin.com/voyager/api/* with:
    • csrf-token:
    • Cookie: li_at=…; JSESSIONID="…"; …
    • x-restli-protocol-version: 2.0.0
    • desktop Chrome UA + linkedin.com Origin/Referer
  4. Responses are Rest.li "normalized" JSON (data + included). The CLI flattens the useful bits.

Same family as:

SkillAuth modelStores secrets?
teams-hack / outlook-hackMSAL refresh token from Teams localStorageyes (outlook-msal.json)
factorial-hacklive page fetch (httpOnly cookies never leave browser)no
linkedin-hackin-tab fetch by default; cookie jar optionalyes — OS keychain, warned 0600 file fallback

LinkedIn needs the offline jar because Voyager is same-site cookie auth and we want CLI use without a live tab on every call. Re-extract when you get 401/403.

Rate Guard (do not skip)

LinkedIn will challenge or ban aggressive automation. Soft daily ceilings live in:

~/.openclaw/workspace/memory/linkedin-activity.json

Stealth design (2026-08-05): pacing is jittered, not metronomic — each wait is base ±random(−300..+1400ms), with an 8% chance of a 15–45s "distraction" pause (LINKEDIN_PACE_STRICT=0 disables). Speed comes from fat payloads + local cache, never from parallelism:

  • Local cache at ~/.openclaw/workspace/memory/linkedin-cache.jsonprofile and company results cached 60h (LINKEDIN_CACHE_TTL_H, prune >7d). Cache hits cost zero requests and zero rate-guard counters. --no-cache forces live.
  • connections defaults to --top 100 in one request (Voyager happily serves fat pages).

Defaults (override by editing limits in that file):

counterdefault / day
profile_views40
messages_read200
messages_sent25
connections_sent15
likes40
sessions15
total_minutes90

Commands that would exceed a counter throw instead of calling Voyager.

message-send additionally requires --i-mean-it. No flag → exit 2, no request.

Human pacing heuristics the agent should follow even under the ceilings:

  • Burst ≤ ~10 profile views, then pause minutes not seconds
  • Prefer search → shortlist → deep profile, not full-graph walks
  • Never auto-connect or auto-message from a cron without an explicit, per-run human brief

Read this before you install. It is the honest version.

What it touches

  • One browser tab that you shared. The default transport runs fetch inside a linkedin.com tab you explicitly clicked Share on in the OpenClaw extension. The skill cannot reach a tab you did not share, and it opens nothing on its own.
  • Your LinkedIn session cookiesli_at, JSESSIONID, and optionally bcookie / bscookie / li_a / lidc. Treat li_at as a password: it is a full sign-in as you, with no second factor. The skill never prints cookie values; session extract-cdp reports names and lengths only.
  • Three files, all mode 0600, all under ~/.openclaw — the credentials fallback, the rate-guard counters (linkedin-activity.json), and the crawl cache (linkedin-cache.json). It reads nothing else on your disk.
  • Two binaries, run with a fixed argument list and no shellsecret-tool (Linux) or security (macOS), for the keychain only.

Where the secret lives

  1. OS keychain, by defaultsecret-tool on Linux, security on macOS, entry openclaw-linkedin-hack / linkedin-session. On Linux the value is passed over stdin, so it never appears in ps. On macOS security takes it as an argument, so it is briefly visible to your own processes.
  2. A 0600 file, only if there is no keychain~/.openclaw/credentials/linkedin-session.json. This path prints a warning every single time it writes, because a session cookie sitting in a plain file is a materially different risk. Force it with LINKEDIN_NO_KEYCHAIN=1 if you prefer.

A successful keychain write deletes the file, so the secret never exists in two places.

What leaves your machine

  • To www.linkedin.com only: the Voyager API calls you asked for, carrying your own cookies — exactly what your browser sends when you use the site normally.
  • To 127.0.0.1:18792: the local OpenClaw browser relay. That is loopback, not the network.
  • To anyone else: nothing. No telemetry, no analytics, no third-party host, no phone-home. The skill has zero dependencies, so there is no transitive package doing it either.
  • Outbound writes to LinkedIn: exactly one endpoint, message-send, and it is refused without --i-mean-it. Everything else is a read.

Third-party data, and the cost of it

Crawling LinkedIn means putting other people's personal data on your disk. Profiles and companies you fetch are cached at ~/.openclaw/workspace/memory/linkedin-cache.json (0600, 60h TTL, pruned after 7 days). The cache is on by default because a cache hit costs zero requests, which is a large part of what keeps this skill under LinkedIn's rate radar — but you may not want it:

LINKEDIN_CACHE=0 node {baseDir}/scripts/linkedin.mjs profile some-vanity-slug

You are responsible for what you do with that data. In the EU, scraped profile data is personal data under GDPR, and a lawful basis is your problem, not the tool's.

What it costs

  • No API key, no subscription, no per-call fee. LinkedIn has no official API here; this rides your own session.
  • The real cost is account risk. LinkedIn restricts and bans accounts for automation. That is why the pacing is jittered, the ceilings are low, and there is no parallelism anywhere in the code. A ban is not reversible by this skill.
  • Session lifetime. Bursts burn li_at — observed 2026-07-29: an external-transport burst dropped the session to a login wall. Slow is the feature.

How to turn it off

node {baseDir}/scripts/linkedin.mjs session logout                # keychain + file
node {baseDir}/scripts/linkedin.mjs session logout --purge-data   # + cache + counters

logout clears both stores and prints LinkedIn's own revoke page:

https://www.linkedin.com/psettings/sessions

Use it. Deleting the local copy does not invalidate the cookie — until you sign that session out at LinkedIn, it stays valid. Uninstalling the skill also does not revoke anything.

What it will not do

There is no endpoint in this skill for connecting, following, liking, posting, endorsing, or deleting. message-send is the only write, and it is flag-gated. The likes and connections_sent counters exist so those actions stay accounted for if they are ever added — today nothing increments them.

CLI Reference

CommandDescription
session extract-cdp [--store]Pull httpOnly li_at via OpenClaw CDP relay (preferred)
session extract-browserPrint in-page extract snippet (often misses li_at)
session store --li-at … --jsessionid …Save cookies (0600) + auto-test
session testGET /voyager/api/me
session statusWhere the session is stored + today's counters
session logout [--purge-data]Erase the session from keychain and file; print LinkedIn's revoke URL. --purge-data also deletes the cached profiles and counters
meMini-profile
profile Profile + positions (+ education)
search people "q" [--top N] [--network F|S|O]People search
search companies "q" [--top N]Company search
connections [--top N] [--start N]1st-degree connections
company Company page summary
posts [--top N]Member share feed (best-effort)
conversations [--top N]Inbox list
messages [--top N]Thread events
message-send --message "…" --i-mean-itSend (gated)
feed [--top N]Home feed (best-effort)
notifications [--top N]Notifications (best-effort)
activity showCounters + limits
activity bump [--by N]Manual counter bump

Extraction: httpOnly li_at

li_at is frequently httpOnly, so document.cookie will not see it. Prefer:

  1. browser(action=cookies, domain="linkedin.com") when the tool path is available
  2. Or CDP Network.getCookies on the shared LinkedIn target through the relay

JSESSIONID is usually readable and doubles as the CSRF token (strip surrounding quotes).

Never paste full li_at values into chat transcripts, git commits, or clawhub packages. Store → test → discard from the message.

Failure Modes

SymptomLikely causeFix
401 / 403Session expired, challenge, or missing csrfRe-login in browser, session extract-cdp --store
302 redirect / redirect loopDead/rotated li_at (CLI uses redirect:manual)Same: re-login + extract-cdp
429LinkedIn rate limitStop for minutes; do not retry in a loop
Rate guard: daily …Soft ceiling hitWait for next day or edit limits deliberately
Empty search resultsVoyager decorationId driftCLI already falls back to /search/hits; re-check with --raw on profile if needed
li_at missing from evaluatehttpOnly cookieUse session extract-cdp, not document.cookie
Tab on /loginSession burned (often after a request burst)Human re-login, open feed, re-share, extract once
Send refusedMissing --i-mean-itIntentional; only pass when a human has explicitly approved that exact message

Architecture

linkedin-hack/
├── SKILL.md
└── scripts/
    └── linkedin.mjs    # zero-dep CLI (session + voyager + rate guard)
  • Zero external deps — pure Node 22+ (fetch built-in)
  • Credentials — OS keychain openclaw-linkedin-hack/linkedin-session; fallback ~/.openclaw/credentials/linkedin-session.json (0600, warned)
  • Activity~/.openclaw/workspace/memory/linkedin-activity.json (0600)
  • Cache~/.openclaw/workspace/memory/linkedin-cache.json (0600, 60h TTL, LINKEDIN_CACHE=0 to disable)
  • API — LinkedIn Voyager (/voyager/api), Rest.li normalized JSON
  • Off switchnode scripts/linkedin.mjs session logout --purge-data

Sibling Skills

SkillWhat it does
teams-hackTeams chat via Graph + MSAL refresh
outlook-hackOutlook read/draft (send code-disabled)
factorial-hackFactorial HR GraphQL in-page

The Full Stack

Pair with outlook-hack for email, whatsapp-ultimate for messaging, and teams-hack for org chat.

Clone it. Fork it. Break it. Make it yours.

Related skills

Post videos, photos, text, and documents to 10 social platforms through a single REST API call.

by victorcavero14375 installs50 stars

Join a video meeting as an AI bot with voice, avatar, and screenshare across four operating modes.

by johnpatternai21 installs8 stars

Query and manage Linear issues, projects, teams, cycles, labels, and comments through a managed OAuth GraphQL endpoint.

by byungkyu518 installs18 stars

Query Twitter/X profiles, tweets, follower events, and KOL data through the 6551 REST API.

by infra403840 installs27 stars

Adaptive web scraping in Python that bypasses anti-bot systems and scales from single requests to concurrent crawls.

by d4vinci399 installs28 stars

Fetch raw ad creative, app, ranking, and revenue data from AdMapix as structured JSON.

by fly0pants4.3k installs296 stars

More from globalcaos

Browse all skills

Give your OpenClaw agent a JARVIS-style British voice with matching dry humor, audio plus a purple chat bubble in one call.

by globalcaos190 installs4 stars

Native WhatsApp channel for OpenClaw with 22 messaging/group actions plus Protocol v2 multi-agent coordination.

by globalcaos116 installs3 stars

One dashboard tracking Anthropic, Gemini, OpenAI, and Manus token usage with budget alerts and a local REST API.

by globalcaos59 installs

Stop sending 'format this JSON' to Opus. Stop sending 'cron job' to GPT. Billing-aware routing guide for choosing among the models already configured in your OpenClaw setup when assigning an agent, sub-agent or cron task — flat-rate first, metered only when justified, budget pressure respected. Not for picking models outside your configuration, and not a runtime proxy.

by globalcaos16 installs

Your agent says 'done' — but did it check? Superpowers turns any OpenClaw agent into a disciplined engineer. Verification iron law (evidence before claims), three-agent code review (build → verify spec → verify quality), systematic debugging (4-phase root cause, three-strike rule), brainstorming gates (design before code), and anti-over-engineering rules. Use when: (1) coding tasks of any complexity, (2) debugging failures, (3) about to claim work is complete, (4) spawning sub-agents, (5) planning features, (6) reviewing code. Inspired by top coding agent methodologies, adapted for OpenClaw multi-agent architecture.

by globalcaos14 installs

Read and search Outlook, inspect attachments, and create or edit drafts without any send endpoint. Uses one short-lived Microsoft Graph access token supplied on stdin for one run; it never stores credentials. Bulk mailbox export is opt-in.

by globalcaos23 installs