Post videos, photos, text, and documents to 10 social platforms through a single REST API call.
Browser
Tinker LinkedIn
Try itYour 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,profilevia 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 burnsli_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.
- Confirm relay is up:
GET http://127.0.0.1:/extension/status→connected:true,count>=1(`` =browser.profiles.chrome-relay.cdpUrlin~/.openclaw/openclaw.json, usually18792) - List tabs (
GET /tabsorbrowser action=tabs) and confirm alinkedin.comtab is shared. Grab itstargetId.
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
- LinkedIn web uses cookies (
li_atsession +JSESSIONID/ CSRF) for Voyager. - The skill seals those cookies in your OS keychain (
secret-toolon Linux,securityon macOS, entryopenclaw-linkedin-hack/linkedin-session). With no keychain present it falls back to~/.openclaw/credentials/linkedin-session.jsonat mode0600and prints a warning every time it writes. Only one copy is ever kept: a successful keychain write deletes the file. - 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
- Responses are Rest.li "normalized" JSON (
data+included). The CLI flattens the useful bits.
Same family as:
| Skill | Auth model | Stores secrets? |
|---|---|---|
| teams-hack / outlook-hack | MSAL refresh token from Teams localStorage | yes (outlook-msal.json) |
| factorial-hack | live page fetch (httpOnly cookies never leave browser) | no |
| linkedin-hack | in-tab fetch by default; cookie jar optional | yes — 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.json—profileandcompanyresults cached 60h (LINKEDIN_CACHE_TTL_H, prune >7d). Cache hits cost zero requests and zero rate-guard counters.--no-cacheforces live. connectionsdefaults to--top 100in one request (Voyager happily serves fat pages).
Defaults (override by editing limits in that file):
| counter | default / day |
|---|---|
| profile_views | 40 |
| messages_read | 200 |
| messages_sent | 25 |
| connections_sent | 15 |
| likes | 40 |
| sessions | 15 |
| total_minutes | 90 |
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
Permissions, Data Flow & Consent
Read this before you install. It is the honest version.
What it touches
- One browser tab that you shared. The default transport runs
fetchinside alinkedin.comtab 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 cookies —
li_at,JSESSIONID, and optionallybcookie/bscookie/li_a/lidc. Treatli_atas a password: it is a full sign-in as you, with no second factor. The skill never prints cookie values;session extract-cdpreports 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 shell —
secret-tool(Linux) orsecurity(macOS), for the keychain only.
Where the secret lives
- OS keychain, by default —
secret-toolon Linux,securityon macOS, entryopenclaw-linkedin-hack/linkedin-session. On Linux the value is passed over stdin, so it never appears inps. On macOSsecuritytakes it as an argument, so it is briefly visible to your own processes. - 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 withLINKEDIN_NO_KEYCHAIN=1if you prefer.
A successful keychain write deletes the file, so the secret never exists in two places.
What leaves your machine
- To
www.linkedin.comonly: 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
| Command | Description |
|---|---|
session extract-cdp [--store] | Pull httpOnly li_at via OpenClaw CDP relay (preferred) |
session extract-browser | Print in-page extract snippet (often misses li_at) |
session store --li-at … --jsessionid … | Save cookies (0600) + auto-test |
session test | GET /voyager/api/me |
session status | Where 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 |
me | Mini-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-it | Send (gated) |
feed [--top N] | Home feed (best-effort) |
notifications [--top N] | Notifications (best-effort) |
activity show | Counters + 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:
browser(action=cookies, domain="linkedin.com")when the tool path is available- Or CDP
Network.getCookieson 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
| Symptom | Likely cause | Fix |
|---|---|---|
401 / 403 | Session expired, challenge, or missing csrf | Re-login in browser, session extract-cdp --store |
302 redirect / redirect loop | Dead/rotated li_at (CLI uses redirect:manual) | Same: re-login + extract-cdp |
429 | LinkedIn rate limit | Stop for minutes; do not retry in a loop |
Rate guard: daily … | Soft ceiling hit | Wait for next day or edit limits deliberately |
| Empty search results | Voyager decorationId drift | CLI already falls back to /search/hits; re-check with --raw on profile if needed |
li_at missing from evaluate | httpOnly cookie | Use session extract-cdp, not document.cookie |
Tab on /login | Session burned (often after a request burst) | Human re-login, open feed, re-share, extract once |
| Send refused | Missing --i-mean-it | Intentional; 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+ (
fetchbuilt-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=0to disable) - API — LinkedIn Voyager (
/voyager/api), Rest.li normalized JSON - Off switch —
node scripts/linkedin.mjs session logout --purge-data
Sibling Skills
| Skill | What it does |
|---|---|
| teams-hack | Teams chat via Graph + MSAL refresh |
| outlook-hack | Outlook read/draft (send code-disabled) |
| factorial-hack | Factorial HR GraphQL in-page |
The Full Stack
Pair with outlook-hack for email, whatsapp-ultimate for messaging, and teams-hack for org chat.
Related skills
Join a video meeting as an AI bot with voice, avatar, and screenshare across four operating modes.
Query and manage Linear issues, projects, teams, cycles, labels, and comments through a managed OAuth GraphQL endpoint.
Query Twitter/X profiles, tweets, follower events, and KOL data through the 6551 REST API.
Adaptive web scraping in Python that bypasses anti-bot systems and scales from single requests to concurrent crawls.
Fetch raw ad creative, app, ranking, and revenue data from AdMapix as structured JSON.
More from globalcaos
Browse all skillsGive your OpenClaw agent a JARVIS-style British voice with matching dry humor, audio plus a purple chat bubble in one call.
Native WhatsApp channel for OpenClaw with 22 messaging/group actions plus Protocol v2 multi-agent coordination.
One dashboard tracking Anthropic, Gemini, OpenAI, and Manus token usage with budget alerts and a local REST API.
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.
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.
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.