September 4, 2026
Is Kaspr Chrome Extension safe?It POSTs Your LinkedIn Session Tokens to api.kaspr.io
A static read of the shipped v2.0.19 package: the upload path, the host, the probe file LinkedIn already asks for, and what each step doesβ¦

By William Scott
8 min read
A static read of the shipped v2.0.19 package: the upload path, the host, the probe file LinkedIn already asks for, and what each step does and doesn't expose.
Kaspr's Chrome extension collects the LinkedIn cookies set for www.linkedin.com and sends the session tokens to Kaspr's own backend. The call lives in the background service worker, at background.api.js:157β169:
js return fetch(${REACT_APP_API_URL}linkedin/sync, { method: "POST", body: JSON.stringify({ userEmail, li_a, li_at, linkedinId, sessionId, force }), });
REACT_APP_API_URL resolves to https://api.kaspr.io/ in background.constants.js:4, so the destination is api.kaspr.io/linkedin/sync, and li_at is the cookie that is your logged-in LinkedIn session. Separately, and before any of that runs, LinkedIn's own page code already knows the extension is installed: the extension ID kkfgenjfpmoegefcckjklfjieepogfhg sits on the list LinkedIn's production JavaScript probes on every page visit, and the file it asks for is assets/images/arrow.svg.
Those are the two most concrete things in the package, so I am putting them first rather than building up to them.
How I got there
I fetched the shipped extension package for v2.0.19 on 2026β06β05 and read it: the MV3 manifest, the background service worker, the constants file, and the content script. I finished the teardown on 2026β06β11 and checked the extension ID against a snapshot of LinkedIn's extension-probe list the same day.
This is a static read of shipped source. I did not capture network traffic, I did not instrument the extension at runtime, and I did not sign up for a hosted account and measure anything server-side. That bounds everything below: I can show you the call the code makes, and I can tell you what LinkedIn is documented to look for, but where a claim depends on what Kaspr's servers subsequently do with a token, I say "appears to" and mean it.
Two pieces of vocabulary, since the rest of this leans on them. AED is the label visible in LinkedIn's own production JavaScript, where scan results ship as an AedEvent β it is not an official LinkedIn feature name, not a researcher's coinage, and LinkedIn has never publicly acknowledged it. It works by silently fetching one declared file from each of thousands of specific extension IDs; a fulfilled response means "installed". BrowserGate is the independent investigation that took LinkedIn's production bundle apart between December 2025 and 2026, published line references and code excerpts, and documented both the array and the event payload (browsergate.eu/how-it-works). The array it tracked held 5,459 entries in December 2025 and 6,167 in February 2026 β roughly a dozen new IDs a day.
What each step does
Before you do anything, the extension answers a question LinkedIn asks. The manifest exposes assets/images/** to any origin through web_accessible_resources, which is what makes chrome-extension://kkfgenjfpmoegefcckjklfjieepogfhg/assets/images/arrow.svg fetchable from a page. The ID was on the probe list when I checked on 2026β06β11, with no removal flag. The consequence is narrow and worth stating precisely: the fact of installation is recorded on page load, with zero user action, and it is one input into a cumulative score rather than a switch that trips.
The cookie read itself is local, and produces nothing. background.events.js:87β89 calls chrome.cookies.getAll({ url: "https://www.linkedin.com" }, β¦), enabled by the cookies permission; the names picked out downstream are li_at, li_a and sessionId, with JSESSIONID also present in the source. Note the scope β this is the cookie set for www.linkedin.com, not the browser's entire cookie store, and it would be wrong to describe it as "all your cookies". Honestly, no detection mechanism attaches to this step at all. Nothing has left the machine and nothing has touched the page. The signal starts one step later.
The upload is the step that changes what LinkedIn can see. Once the tokens are on api.kaspr.io, anything done with them presents the same session from a second address, and one session cookie alive on two IPs in parallel is among the loudest of the classic signals. A secondary one: LinkedIn's 48-point request fingerprint is assembled in the page and rides along in API request headers, and a server replaying a copied cookie has never built the fingerprint the original device produces. Both of those describe what would follow from server-side use of the token β what I observed is the outbound POST. That Kaspr's infrastructure then acts on LinkedIn with it is highly likely, given the product's server-side workflow endpoints (workflows/inputBlock, workflows/all) and the vendor's own description of running enrichment workflows, but I did not watch it happen. I also found no way to decline: the sync runs at first install and on reconnect, and there is no privacy toggle among the extension's settings.

A widget is injected into every LinkedIn page. The manifest runs linkedinWidget.js as a content script at document_idle on https://.linkedin.com/, and the scripting permission additionally allows runtime injection. This is the sidebar users see, and it auto-opens. The relevant scanner here needs no target list at all: it walks the page's DOM looking for the chrome-extension:// substring and reports what it finds, which is exactly what a persistent injected sidebar provides.
Scripted clicks are in the source. The audit records synthetic_events = true, with the pattern synthetic_event appearing 8 times and programmatic_click twice in linkedinWidget.js. Those are counts of how often each pattern occurs in the shipped code, not a count of events observed at runtime β I never ran the thing. The mechanism is the read-only isTrusted flag every DOM event carries: a human click is true, anything a content script synthesises is false, and a content script cannot flip it. The honest qualifier is that this is a cheap check available to LinkedIn rather than a demonstrated tripwire.
Three origins can ask the extension for your session on demand. externally_connectable lists https://app.kaspr.io/, https://staging.kaspr.io/ and http://localhost:3000/*, and the GET_LINKEDIN_SESSION handler at background.events.js:303β313 returns the LinkedIn cookie jar plus a CSRF token to any of them. No LinkedIn detection vector maps to this step, and I am not going to invent one. It is a security and privacy exposure: any JavaScript running on those three origins β including a staging host and a localhost development port β can request the session, so a compromise or an XSS on any of them reaches every installed user's LinkedIn login.
What is absent, which cuts the other way
I found no direct Voyager or GraphQL calls from the browser (direct_linkedin_api = false); profile and email lookups are relayed through api.kaspr.io after the sync, so the "API accessed without the page traffic around it" anomaly does not apply at the browser layer. There are no declarative_net_request rules and no telemetry blocking, meaning Kaspr makes no attempt to suppress LinkedIn's own tracking endpoints β read neutrally, that is both an absence of anti-detect behaviour and an absence of interference, so the injected DOM and the synthetic events are collected as-is. I also found no remote code execution: no eval(), no new Function(), no remote script injection in the readable background sources.
Pacing is thin on the extension side. Three settings were extractable: delay (default 0, also seen as 1) and interval (default 1 second). No daily cap, no working-hours scheduler, no randomiser, no mouse-movement emulation. The workflows/inputBlock endpoint indicates the automation parameters live server-side, where they cannot be inspected β so "not found" here means not present in the readable client, not that no pacing exists anywhere. For scale, LinkedIn's current invite ceiling is roughly 100 a week for most accounts, and volume is scored regardless of which tool produces it.
One thing I could not test at all: there is no live two-account cloud measurement for Kaspr, so no exit IP and no third-party IP reputation score appear anywhere in this piece. That is architectural rather than an oversight. A live test works by signing into a vendor's own hosted browser and reading back the address it assigns you; a cookie bridge has no separate vendor login surface, so there is no cloud-side address to point a check at in the first place.
What users report
Kaspr has 819 labeled reviews in the review corpus I work from, all on G2. Fourteen of them carry a safety-topic mention. That is a count of labeled mentions in a self-selected set, not an incidence rate, and it is not a ban rate for Kaspr or anyone else.
"LinkedIn often kicks you out becuase Kaspers automation seems to breach its terms of service. I do not use this feature but cannot turn it off and therefore am worried LinkedIn will ban me." β G2, 4.5 stars, small business, 2023β02β16 (typos as written)
The detail I would not have predicted is "cannot turn it off". It lines up with the manifest: I found no in-extension privacy control and no opt-out for the session sync, which runs at install and on reconnect. A user's frustration and a code finding independently describing the same thing is about as good as this kind of evidence gets.
The other side is represented too. The single positive safety-topic mention in that set reads, in full, "not intrusive on Linkedin" (G2, 4.5 stars, 2023β04β03). Taken as a statement about the user's experience, that is fair β the sidebar is unobtrusive to work alongside. It is not a statement about what LinkedIn sees, and the two are separable: the ID probe fires on page load and the injected widget is in the DOM whether or not the sidebar feels intrusive.
Which makes one vendor-side detail worth putting next to a code-side one, without a verdict attached. Kaspr's help center lists "Hide the Kaspr Chrome Extension" among its LinkedIn profile-visit guidelines (help.kaspr.io, read 2026β08). Hiding the widget changes what the user sees. The ID probe does not depend on the widget being visible.
FAQ
Is Kaspr safe to use on LinkedIn? It depends on what you are weighing. Reading the shipped extension code (v2.0.19, June 2026), Kaspr copies your LinkedIn session tokens to api.kaspr.io, injects a widget into every LinkedIn page, and its ID is on LinkedIn's extension-probe list. Those are cumulative restriction signals, not a guaranteed outcome.
Is Kaspr a Chrome extension or a cloud tool? Both, and the order matters. The Chrome extension reads your LinkedIn cookies locally and POSTs li_at, li_a and sessionId to api.kaspr.io/linkedin/sync; the enrichment and workflow logic then runs on Kaspr's servers. The extension is the bridge, not the engine.
Does Kaspr collect user data? From the extension's own code: your LinkedIn session tokens (li_at, li_a, sessionId), your linkedinId and account email go to api.kaspr.io; profile fields you look up (name, job title, company, picture URL) follow; product telemetry goes to Mixpanel, feature flags to LaunchDarkly, and the uninstall survey URL carries your email to Tally.
Can Kaspr get my LinkedIn account restricted? Detection is not enforcement β LinkedIn scores many cumulative signals. Kaspr's architecture contributes several: a listed extension ID, an injected page widget, scripted isTrusted:false clicks, and a session that appears to be used from the vendor's address as well as yours. Users on G2 do report restrictions.
Is Kaspr GDPR compliant? France's CNIL fined Kaspr β¬240,000 on 5 December 2024 over contact data collected from LinkedIn β including details restricted to a profile's connections β and a retention period it found disproportionate, with a compliance deadline of 18 June 2025 (source: cnil.fr). Kaspr states that it aligns with GDPR and CCPA.
The final conclusion
None of this is a tripwire. LinkedIn runs a cumulative scoring model, and a listed extension ID, an injected widget and a session used from a second address each add to a score rather than flip a switch. No architecture removes restriction risk either, because the behavioural layer β volume, rhythm, acceptance rate β judges humans and tools alike; a smaller technical surface is a smaller surface, not immunity.
And all of it is version- and date-specific. I read v2.0.19, fetched 2026β06β05 and torn down 2026β06β11. Every "no cap found", "no jitter found", "no remote code found" means not present in the readable shipped source at that version, and the pacing logic demonstrably lives somewhere I cannot see. Vendors change infrastructure; a later build may look different, and the useful move is to re-read it rather than to trust either the vendor's summary or mine indefinitely.
The full line-by-line teardown, with the code citations for each step above, is at safe-outreach.com/is-kaspr-safe.