Is Similarweb - Website Traffic, AI Traffic & SEO Checker safe?
Similarweb is high risk. We observed a Mixpanel event from the Similarweb extension via mpps.similarweb.com/track. The decoded event held the embedded Mixpanel token, a persistent device ID, the current welcome-page URL, and context for a button interaction.…
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Similarweb sends extension usage events to Mixpanel
We observed a Mixpanel event from the Similarweb extension via mpps.similarweb.com/track.
The decoded event held the embedded Mixpanel token, a persistent device ID, the current welcome-page URL, and context for a button interaction.
You install or use the Similarweb extension.
The observed traffic came from an extension button interaction during the extension flow.
The extension sends a Mixpanel analytics event with a persistent device identifier.
The observed event was routed through mpps.similarweb.com/track and included the current welcome-page URL.
| Field | Value | Why it matters | |
|---|---|---|---|
Event name | button | Shows the type of extension interaction that was recorded. | |
Persistent device ID | $device:61b6a35c-f2b2-46e5-a11c-074a4a6b28b9 | Lets analytics connect extension events from the same browser across sessions. | |
Current page URL | https://www.similarweb.com/corp/extension-welcome-chrome/ | Shows which page was open when the extension recorded the event. | |
Mixpanel project token | 7ccb86f5c2939026a4b5de83b5971ed9 | Identifies the analytics project that received the event. |
The shipped background script defines the Mixpanel endpoint and token
const M = {
FETCH_DATA: "fetchData",
FETCH_IDENTITY: "fetchIdentity",
IS_INSTALLED: "isInstalled",
OPEN_LINK: "openLink",
OPEN_OPTIONS_PAGE: "openOptionsPage",
OPT_IN: "enableAutoIcon",
OPT_OUT: "disableAutoIcon",
TOGGLE_POPUP: "togglePopup",
TOGGLE_POPUP_FROM_IFRAME: "togglePopupFromIframe"
},
F = {
ENDPOINTS: {
TRACK: "https://api.mixpanel.com/track"
},
TOKENS: {
SANDBOX: "2a36d6f836516f4677bde7726425a84d",
PRODUCTION: "7ccb86f5c2939026a4b5de83b5971ed9"
},
SITE_TYPE: "similarweb extension"
};Install and usage events are sent through Mixpanel tracking helpers
xe = function(e, t, r) {
var n = chrome.runtime.getManifest(),
i = n.version,
a = ye(),
o = Se(t, r);
fetch(F.ENDPOINTS.TRACK, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify([{
event: e,
properties: ke(ke({}, o), {}, {
browser: a,
version: i,
token: b ? F.TOKENS.SANDBOX : F.TOKENS.PRODUCTION
})
}])
}).then((function() {
X("Mixpanel event:", ke({ category: e }, o));
})).catch(Y);
};Ce = function() {
var e = t(i().mark((function e(t) {
var r, n;
return i().wrap((function(e) {
for (;;) switch (e.prev = e.next) {
case 0:
r = t.reason, e.t0 = r, e.next = "install" === e.t0 ? 4 : "update" === e.t0 ? 8 : 15;
break;
case 4:
return e.next = 6, chrome.tabs.create({ url: Ee() });
case 6:
return xe("background", "install"), e.abrupt("break", 16);
case 8:
return e.next = 10, N(R.IS_LIMIT_ANNOUNCED);
case 10:
if (n = e.sent, n) { e.next = 14; break; }
return e.next = 14, B(R.IS_LIMIT_ANNOUNCED, !1);
case 14:
case 15:
return e.abrupt("break", 16);
case 16:
case "end":
return e.stop();
}
}), e);
})));
return function(t) { return e.apply(this, arguments); };
}();Ig = function(t, e, i) {
var n = jg(e, i);
Tg().track(t, n), Vp("Mixpanel event:", Pg({
category: t
}, n));
};- api.mixpanel.com
Endpoint configured in the shipped background tracking helper for Mixpanel events.
- mpps.similarweb.com
Observed proxy endpoint that received the decoded Mixpanel event during traffic capture.
- api-js.mixpanel.com
Default API host inside the bundled Mixpanel JavaScript SDK used by the panel.
Similarweb loads a remote configuration file from an S3 bucket at startup
On startup Similarweb's worker fetches JSON from an S3 bucket, not similarweb.com, with no signature/schema check, parsed into feature toggles and rewrite rules applied before URLs reach Similarweb.
Sessions returned only analytics toggles.
You start Chrome, or install the extension, with Similarweb enabled.
No page visit, click, or interaction with the extension is needed.
The extension downloads a settings file from an Amazon S3 bucket and saves it into your synced Chrome storage.
The file it receives decides which analytics systems run and, through a second code path, how the URLs of pages you visit are rewritten before being sent to Similarweb.
The S3 file is kept as received. It's written to synced storage, not local, so it travels to every Chrome profile you're signed into.
chrome.storage.sync, key 'config'{
"matomo": {
"enabled": true
},
"mixpanel": {
"config": {
"persistence": "localStorage"
},
"enabled": true
}
}Startup fetch and persistence, from the extension's shipping background bundle.
const ENDPOINTS = {
CONFIG: "https://sw-extension.s3.amazonaws.com/config.json",
DATA: "https://data.similarweb.com/api/v1/data",
GLOBAL_RANK: "https://rank.similarweb.com/api/v1/global",
IDENTITY: "https://data.similarweb.com/api/v1/identity"
};
const STORAGE_KEYS = {
CONFIG: "config",
// ...
};async function fetchRemoteConfig() {
try {
const response = await fetch(`${ENDPOINTS.CONFIG}?v=${Date.now()}`);
const config = await response.json();
await storageSet(STORAGE_KEYS.CONFIG, config); // chrome.storage.sync.set({ config })
} catch (err) {
logError(err);
}
}(async function startup() {
try {
initA();
initB();
installIdentityHeaderListener();
await fetchRemoteConfig();
} catch (err) {
logError(err);
}
})();How the stored configuration is consumed: settings loader and URL-rewriting rule builder.
fetch(this.dataEndpoint, { method, headers, body }).then(response => {
const sessionHeader = response.headers.get("x-session-id");
if (sessionHeader) {
try {
const settings = JSON.parse(atob(sessionHeader));
runHook.setSettings(settings); // replaces the live settings object
} catch (e) {}
}
// ...
});createGetClasses(pii) {
if (typeof pii === "undefined") return;
// config.data is either a base64-encoded JSON string or a plain object
const rules = typeof pii.data === "string"
? JSON.parse(atob(pii.data || "e30="))
: pii.data;
// "urlparams" entries are "keyRegex=valueRegex[=type]" triples
const urlparams_m = {};
Object.keys(rules.urlparams || {}).forEach(name => {
const parts = rules.urlparams[name].split("=");
if (parts.length === 2 || parts.length === 3) {
urlparams_m[name] = { kr: parts[0], vr: parts[1], t: parts[2] };
}
});
rules.urlparams_m = urlparams_m;
const handlers = [];
try {
if (typeof rules.sitewhitelist === "string")
handlers.push(new SiteWhitelistHandler(true, rules.sitewhitelist));
if (typeof rules.blacklist === "object" && Object.keys(rules.blacklist).length)
handlers.push(new BlacklistHandler(true, rules.blacklist));
if (typeof rules.paramwhitelist === "string"
&& typeof rules.urlparams_m === "object"
&& typeof rules.paths === "object"
&& Object.keys(rules.paths).length)
handlers.push(new ParamWhitelistHandler(false, rules.paramwhitelist, rules.urlparams_m, rules.paths));
} catch (e) {}
this.holdings_list = handlers; // applied to URLs before they are sent
}- sw-extension.s3.amazonaws.com
S3 bucket serving config.json, fetched every worker start and applied with no integrity checks. Not similarweb.com; the bucket's own access control governs what the extension gets.
- data.similarweb.com
Similarweb's data/identity API. Its x-session-id header decodes to base64 JSON fed into the same settings loader, a second server-controlled config channel.
- rank.similarweb.com
Similarweb's global rank API, queried for site metrics after URLs have been processed by the configured rewriting rules.
The startup fetch and the storage write are confirmed: two independent dynamic-analysis sessions each captured the background service worker performing `GET https://sw-extension.s3.amazonaws.com/config.json`, and the post-session storage snapshot held the exact response body under `chrome.storage.sync['config']`.
The configuration served at the time of testing contained only Mixpanel and Matomo feature toggles. The `urlparams`, `sitewhitelist`, `blacklist`, `paramwhitelist` and `paths` fields that the rule builder is written to consume were not present in that response, so we did not observe URL-rewriting rules being delivered. Those code paths are present in the shipping bundle and are reached from the same stored `config` object; what they do on a given day depends on the document the bucket returns at that moment.