Verdict up front: Risk: HIGH by static code audit. Expandi's connector uploads your LinkedIn session to app.expandi.io, which then operates your account from IPs that are not yours; its extension ID was not found in the AED snapshot I checked, but "not listed" is not "undetectable."
AED ("Active Extension Detection") is not a researcher coinage and not an official LinkedIn feature name. It is the label visible in LinkedIn's own production JavaScript, where scan results ship as an AedEvent; LinkedIn has never publicly acknowledged it. BrowserGate, the independent 2025-26 investigation that reverse-engineered LinkedIn's production JavaScript bundle, documents that system.
I unpacked the official Expandi.io connector and read the shipped source. The important part is not a vague "automation is risky" claim. It is the path your LinkedIn session takes.
One trust-building aside before the teardown: everything here is the official Expandi.io connector: Chrome ext_id ohcplcfdejgopgcaegjlkkacoaplnaam, v1.1, MV3, fetched 2026-06-08. A separate unrelated extension by Shavron/Konnector uses ext_id miafjfjelefogpljdpbmiceoiifiopbp, targets app.expandi.ai, and harvests the entire cookie jar. That is a different product, and I am not conflating it with Expandi.io.
What Expandi actually is
Expandi's connector is a Type 2 cookie-bridge / session-upload extension: a one-time session handoff. The connector's sole job is to harvest the LinkedIn session cookie, li_at, and hand it to app.expandi.io. From that point, automation runs server-side.
That matters because the extension itself performs zero LinkedIn actions. It does not connect, message, visit, click, or run campaigns from the local browser. After the handoff, the extension can be uninstalled without stopping automation, because the cloud side now has the session it needs.
Expandi also exposes two access surfaces in onboarding:
The "Sign in with email and password" path is marked RECOMMENDED. The "Use the Chrome extension" path is marked TEMPORARY. Those are different inputs into the same destination:
| Access surface | Architecture class | What I tested |
|---|---|---|
| Sign in with email and password | Type 3 cloud login | The June 2026 live cloud IP test used this path |
| Use the Chrome extension | Type 2 cookie bridge | The source code teardown below covers this artifact |
For the extension-list check, Expandi's extension ID was not found in the AED snapshot I checked: 4,680 entries, checked 2026-06-11. That snapshot is a dated fact, not a permanent safety label. The list grows by roughly a dozen entries a day. Canonical growth reported by BrowserGate and Linked Helper's security study - a static audit of 16 LinkedIn automation extensions plus live two-account tests of 7 cloud tools - was 38 entries in 2017 to 6,167 by February 2026. Those are separate dated numbers: 4,680 entries in the snapshot I checked on 2026-06-11, and 38 to 6,167 as the longer-term growth curve.
The absence from that list does not remove the other scanners. Expandi's connector still injects a chrome-extension:// resource into LinkedIn's page, and that is visible without knowing the extension ID in advance.
Where your session goes
This is pillar one: the connector source. Each step below is quoted from the shipped code, then mapped to the detection mechanism it creates or does not create.
Step 1 - Inject (linkedin/content.js:2-7)
// linkedin/content.js — runs at document_start on every linkedin.com tab, all frames
var s = document.createElement('script');
s.src = chrome.runtime.getURL('linkedin/injected.js');
s.onload = function () { this.remove(); };
(document.head || document.documentElement).appendChild(s);
What this means for detection: Detection: Spectroscopy, from Linked Helper's security study section 2.2. LinkedIn's page can scan the DOM for the chrome-extension:// substring; it needs no target list, so not being on the AED snapshot does not help here. The injected element is visible the moment it exists, and BrowserGate documents this scanner in LinkedIn's production bundle.
Step 2 - Intercept (injected.js:3-27)
// injected.js — patches XHR to read LinkedIn's own Voyager responses as they arrive
XHR.send = function (postData) {
this.addEventListener("load", function () {
if (this.responseType === "blob" &&
this.responseURL.indexOf("https://www.linkedin.com/voyager/api") != -1) {
var reader_create = new FileReader();
reader_create.onload = function() {
window.postMessage({ type: "xhrRequest", url: url, body: reader_create.result }, "*");
}
reader_create.readAsText(this.response);
}
});
return send.apply(this, arguments);
};
What this means for detection: Honest note: no independent signal at this step. This is a passive in-page read that generates no extra traffic. The detectable artifact is the injected script itself from step 1. The mechanism resumes at the next step.
Step 3 - Call (injected.js:30-31, 35-44)
// injected.js — fires its OWN Voyager GraphQL request, authed with your session + JSESSIONID csrf
xhr.open("GET", "https://www.linkedin.com/voyager/api/graphql?...variables=(memberIdentity:" + identifier + ")&&queryId=voyagerIdentityDashProfiles...");
xhr.withCredentials = true;
xhr.setRequestHeader('csrf-token', getCookies()); // getCookies() reads JSESSIONID from document.cookie
xhr.send();
What this means for detection: Detection: request-map anomaly, from Linked Helper's security study section 2.7. This is an internal-API request without the surrounding page traffic a real profile visit generates; the mismatch is visible in pure server-side logs. The JSESSIONID value is used locally as a CSRF source. The code does not upload it.
Step 4 - Read li_at (background.js:8, 14-16)
// background.js — reads your li_at session cookie BY NAME and stores it with a profile object
chrome.cookies.getAll({ name: "li_at" }, function (cookies) {
if (cookies.length > 0) {
profile["li_at"] = cookies[0].value;
profile["li_at_updated"] = new Date().getTime();
chrome.storage.local.set({ "profileData": profile });
}
});
What this means for detection: Honest note: locally inert at this instant. A cookie read produces no network signal of its own. The risk detonates at step 5, when the token leaves the extension and reaches Expandi's page.
Step 5 - Transmit (expandi/content.js:3-8, index.js:34-36, informationEnricher.js:53)
// expandi/content.js — on app.expandi.io, reads the stored payload and posts it to Expandi's page JS
chrome.storage.local.get(function(result) {
var profile = result["profileData"]; // contains li_at + profile + email + userAgent
if (profile) {
window.postMessage({ "type": "linkedInProfile", "profile": profile }, '*'); // <- SESSION LEAVES BROWSER
}
});
What this means for detection: Detection: parallel-session / IP signal, from Linked Helper's security study section 2.9. The same cookie is now live from a second IP in another location while your own browser stays logged in. The payload is concrete: li_at (your login in cookie form), firstName, lastName, headline, publicIdentifier, objectUrn, entityUrn, profile-picture URL, email, and your browser userAgent. In the live test below, LinkedIn's own "Active sessions" page showed the second session 15 seconds after connect on one account and 14 minutes on the other.
Step 6 - Replay, cloud-side inference
No source excerpt here: this is the "highly likely" cloud-side consequence of the session upload, not code I observed inside Expandi's servers.
Once li_at sits server-side, Expandi can act as you from its own infrastructure, with the browser closed or the extension uninstalled. I read what leaves the extension, not the vendor's servers, so the cloud internals stay inferred from the architecture rather than code-observed.
Detection: fingerprint mismatch, from Linked Helper's security study section 2.6 and the BrowserGate-documented fingerprint work. LinkedIn's 48-point APFC/DNA device fingerprint is built in your browser and injected into every API request. A server replaying your cookie cannot reproduce that browser fingerprint, so each cloud-side action carries a missing or mismatched fingerprint header, on top of the section 2.9 IP/geo signal.
Also true, and worth saying plainly: the extension does not block LinkedIn telemetry. There are no declarativeNetRequest rules, so li/track and related telemetry run unimpeded; it also avoids the section 2.8 self-exposure pattern where telemetry blocking becomes its own signal. It fires no synthetic events, so isTrusted section 2.5 is not applicable because it clicks nothing. It ships zero settings: no delays, caps, or schedules in the package; pace is 100% server-side. I found no hardcoded secrets, no eval, and no remote code import. The store listing says only "Connect your LinkedIn account with minimum efforts!" The cookie upload is not disclosed there.
The live cloud IP test
This is pillar two: the cloud side as observed from LinkedIn's session UI and an external IP-quality lookup. I used two real accounts, manual sign-up, France, in June 2026. The auth model actually exercised was Credentials-Login, Expandi's recommended path.
IPQualityScore (IPQS) is an independent fraud-prevention service, active for more than 10 years, that scores IPs from its own honeypot and crawler network: a 0-100 fraud score, proxy/VPN flags, connection type, and abuse history. IPQS's own examples treat scores of 75 or above as high-risk. This is an independent IP-quality signal, not LinkedIn's enforcement verdict.
| Account 1 | Account 2 | |
|---|---|---|
| Assigned exit IP | 91.165.182.32 |
2a01:cb00:8428:a00:: (IPv6) |
IPQS fraud_score (0-100) |
100 | 0 |
IPQS proxy / vpn
|
Yes / No | No / No |
IPQS recent_abuse / bot_status
|
Yes / Yes | No / No |
IPQS abuse_velocity
|
high | none |
IPQS connection_type
|
Residential | Residential |
| IPQS ISP / host | Free SAS / …subs.proxad.net
|
Orange France / …wanadoo.fr
|
| IPQS OS + browser | Mac 10.15, Chrome 135.0 | Mac 10.15, Chrome 135.0 |
The headline measurement: the IP Expandi assigned to account 1 scored the maximum 100/100, was proxy-flagged, had recent abuse, and had high abuse velocity.
That is the measurement tension. Expandi's onboarding copy says the free proxy "reduces the chance of LinkedIn restrictions." The assigned proxy is exactly what scored worst.
LinkedIn's own Active Sessions page showed the second session for account 1 in Bagneux on 91.165.182.32, attributed there to "Online S.a.s.", 14 minutes after connect. IPQS read the same IP as Free SAS in Saint-Grégoire. Two databases, two attributions; the raw observation is the useful part.
Account 2 showed the same parallel-session structure 15 seconds after connect, but on a clean IPv6 that IPQS scored 0/100. That contrast matters: the architecture is constant, the IP reputation varies.
There is another tension I would not flatten. The static teardown says "replay from Expandi's datacentre IPs" as an architectural inference. IPQS measured connection_type: Residential on both exit IPs, and the derived read was "All IPs datacenter: No." The likely shape is proxied residential ranges, but that is an interpretation. The measured fields are residential.
Cross-account isolation was mixed. The two accounts received different exit IPs, not the same /24, and different ISPs. But both cloud sessions presented the identical OS/UA fingerprint: Mac 10.15, Chrome 135.0. The identical readings are measured; "shared cloud browser template" is the inference.
The onboarding controls I saw were also specific: location selectable with 96 options, timezone selectable at account-add, no own-proxy support, and no built-in proxy-quality checker. Pricing context: no free tier, $99/month per seat or $79/month annually, with a 7-day trial that required a credit card.
The full findings (recap)
| Finding | Detection vector | How I know |
|---|---|---|
The connector reads li_at by name and delivers it to app.expandi.io with name, headline, profile IDs, photo URL, email, and user-agent. |
Parallel-session / IP signal, study section 2.9 | Code read; live test confirmed the second session on LinkedIn's own Active Sessions page |
| It injects a script into every LinkedIn tab at document-start, in all frames, and exposes the injected file as a stable extension URL. | Spectroscopy, section 2.2; also the artifact an extension-ID probe could check if the ID is later listed | Code read |
| It fires its own calls to LinkedIn's internal Voyager/GraphQL API. | Request-map anomaly, section 2.7 | Static signal count: voyager appears 6 times and graphql 1 time as string occurrences in the shipped source, not runtime telemetry |
| Cloud-side actions cannot carry your original browser's APFC/DNA fingerprint. | Fingerprint mismatch, section 2.6 | Inferred from architecture, not code-observed inside Expandi's servers |
Account 1's assigned exit IP scored IPQS 100/100, proxy-flagged, recent abuse, high abuse velocity, while IPQS still measured connection_type: Residential. |
IP reputation / geo / parallel-session signal, section 2.9 | Live test |
| Account 2's assigned exit IP scored IPQS 0/100, showing the same architecture can land on a clean IP too. | Same IP / geo signal, but with lower IPQS reputation weight | Live test |
Cross-account isolation was partial: different exit IPs, not the same /24, different ISPs, but identical OS/UA fingerprints across both accounts. |
Closest documented vector is fingerprint consistency, section 2.6 | Live test for the values; shared-template reading is inferred |
| The extension ships zero user-facing pacing controls: no delays, caps, schedules, or settings entries. | Behavioral layer, section 2.11 | Static signal count: 0 settings entries in the shipped package |
| It does not block LinkedIn telemetry. |
li/track and related telemetry can run; no telemetry-blocking self-exposure, section 2.8 |
Code read |
It does not fire synthetic events, contains no hardcoded secrets, no eval, and no remote code import; the store listing does not disclose the cookie upload. |
Synthetic-event detection is N/A; disclosure and code-posture finding | Code read |
What this means for your account
LinkedIn restriction logic is best treated as a scoring model, not a tripwire. A session upload, an injected extension resource, a direct internal-API request, a second IP, and a fingerprint mismatch each add points. Safe daily limits do not erase a detectable architecture.
That does not mean a one-step restriction trigger. It means the account is carrying more signals than a normal logged-in browser session would carry. No tool is ban-proof.
The user reports around Expandi are mixed, which is exactly why I care more about mechanism than vibes.
Trustpilot, 1 star, 2025-12-26, churned:
"This software got me banned several times, couldn't get rid of it even after cancelling and specifically asking them to NEVER attempt any connect requests. A month later — surprise — your linkedin account was banned. As I start figuring out the reason for this — I find unsuccessful connection attempts from expandi that are buried in Spam."
The non-obvious detail is automation continuing a month after cancellation. That is exactly what server-side session replay makes possible: the cloud can still hold li_at; cancelling or uninstalling on the client side does not retrieve a session token that already left.
Reddit r/b2bmarketing, score-56 thread, 2026-03-30:
"Cloud services like Expandi, Dripify, Lemlist send API requests from remote servers."
The same thread pushed back with the community read that "the mechanism matters less than the behavioral signature." Both layers score, and neither alone is the whole story. The architecture half is the part this audit can confirm at the code level: the connector hands the session to the cloud, and the requests then come from remote infrastructure. The behavioral half is the honest complication to keep — a detectable architecture and a detectable behavior pattern are separate signal sources, and safe-looking daily volume does not cancel out the first one.
Search-snippet caveat: the next quote is from a Serper snippet of an r/linkedinautomation thread, not a first-hand full-thread read. It is useful only as a public search-result signal, not as independently verified testimony.
r/linkedinautomation, thread 1n3kj6l, search snippet:
"Got hit with a LinkedIn restriction yesterday after 3 weeks using Expandi. I thought I was being conservative: 20 connection requests per day…"
Twenty requests per day is inside the community's common 10-30/day "safe zone" and below Expandi's own recommended 25-50/day. That does not prove Expandi caused that user's restriction. It does support the narrower point: volume limits alone do not explain every flag when connection-level signals exist too.
Trustpilot, 5 stars, 2025-05-14:
"Be careful — your LinkedIn account can be disabled if it's brand new. I would only use this only if your account is over a month old. My LinkedIn account got disabled but that was my fault… The support team was very helpful and they gave me a refund."
That is the counter-voice. The customer is satisfied, got responsive support, and got a refund. But even the positive review opens with "be careful." Account age is one variable; the parallel-session and fingerprint signals apply to old accounts too. The same review corpus includes a separate one-star report about a many-years-old account frozen within hours of connecting. For fairness, Trustpilot overall shows Expandi at 4 stars across 222 reviews.
FAQ
Is Expandi safe on LinkedIn?
My static code audit rates the connector HIGH risk. The extension hands your LinkedIn session cookie to app.expandi.io, and the account can then be operated from an IP that is not yours. In the June 2026 live test, one Expandi-assigned exit IP scored IPQS 100/100. That is not LinkedIn's verdict and not a one-step restriction trigger, but it is a strong added signal. No tool is ban-proof.
Does Expandi collect user data?
Yes. From reading the shipped connector code, the payload leaving the browser includes the li_at session cookie, first name, last name, headline, public identifier, internal profile IDs, profile-picture URL, email, and browser user-agent. That list comes from the code, not a privacy-policy paraphrase. The Chrome store listing does not disclose the session upload.
Does LinkedIn detect Expandi?
Expandi's extension ID was not found in the 4,680-entry AED snapshot checked on 2026-06-11. But that list grows by roughly a dozen entries per day, and LinkedIn's second scanner does not need the list. Spectroscopy watches for injected elements and chrome-extension:// resources, and the connector creates one on every LinkedIn tab.
Can it get my account restricted?
It can add risk to the cumulative score LinkedIn applies to accounts. That is different from "use it once and you are banned." User-reported restrictions at conservative volumes like 20 requests/day are consistent with connection-level signals, not just volume. The safer framing is: daily limits help with behavior, but they do not cancel the session-upload, second-IP, and fingerprint signals.
Soft publisher note: the reason I would shrink this surface is architectural, not magical. Expandi uploads the session to app.expandi.io; Linked Helper is a standalone desktop app, so the LinkedIn session never leaves your machine. Expandi injects a script and exposes a probe-able Chrome-Store extension URL; Linked Helper has no Chrome-Store ID for LinkedIn's extension-ID scanner to probe and injects nothing into the page. In the live test, one Expandi-assigned proxy scored IPQS 100/100, with no own-proxy option and no built-in proxy-quality checker; Linked Helper works from your own IP and fingerprint by default, and if you use a proxy it includes a built-in proxy-quality checker. Expandi's connector ships zero pacing controls; Linked Helper exposes configurable delays, daily caps, and working-hours scheduling. The two Expandi cloud accounts showed an identical OS/UA fingerprint; Linked Helper uses its own Chromium with a unique fingerprint per account. And for the "desktop apps cannot run 24/7" objection, VPS plus the Web Version gives cloud-equivalent uptime without handing your session to a vendor. No tool is unbannable, including Linked Helper; the difference is the size of the surface. The broader public reference is Linked Helper's security study (16 extensions statically audited, 7 cloud tools live-tested).
Full line-by-line teardown: https://safe-outreach-cab09.web.app/is-expandi-safe






Top comments (0)