Is BeLikeNative: Write English like a native. Paraphrase, Rewrite, Translate safe?
BeLikeNative sends selected text from any website to its AI backend and transmits telemetry including visited domains to the same server.
When a user selects text and triggers a keyboard shortcut or toolbar button, the extension forwards that text to backend.belikenative.com with no domain restrictions — text selected on any page can be sent. The extension also runs a background telemetry system that batches and sends event data every 60 seconds, including the current page's domain, browser platform details, a persistent anonymous identifier, and user subscription and usage metrics.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Telemetry sends page context and usage metrics to BeLikeNative
We observed a POST to backend.belikenative.com carrying telemetry: session, ext/browser version, platform, locale, analytics ID, plan, fix count.
Queued from the content script and worker; can attach the page domain to errors.
You browse websites while BeLikeNative is installed.
The manifest runs the content script on every URL pattern.
The extension queues telemetry that can include page domain context and usage metrics.
Queued events are sent to the BeLikeNative backend in JSON batches.
| Field | Value | Why it matters | |
|---|---|---|---|
Session identifier | 6f2b1bb0-5a74-4e3c-b9ab-4f692f80f5c1 (illustrative) | Lets separate events from the same browser session be grouped together. | |
Extension and browser versions | extension 1.8.5; Chrome 148.0.0.0 | Shows which extension build and Chrome version produced the telemetry. | |
Platform and language | Linux x86_64; en-US | Adds device and locale context to the event stream. | |
Current page domain | docs.example.com (illustrative) | Can show which website was open when an extension error or message failure happened. | |
Analytics identifier | 0000000000000000 | Lets analytics events stay linked across browsing sessions after installation. | |
Plan and fix metrics | plan free; fixes 0 | Shows account tier and usage counters such as the number of corrections made. |
Telemetry is uploaded every minute, and the queue can flush sooner after 10 events are waiting.
Telemetry construction, batching, persistent analytics ID, and page-domain context
function b(e, t, r) {
if (!e) throw new Error("type required");
const n = function() {
if (i) return i;
let e = "unknown";
try {
e = chrome.runtime.getManifest().version || e
} catch {}
return i = {
v: e,
c: h(navigator.userAgent),
p: navigator.platform || "unknown",
l: navigator.language || "unknown"
}, i
}(),
o = {
sessionId: s || "pending",
extensionVersion: n.v,
chromeVersion: n.c,
platform: n.p,
locale: n.l,
type: e,
timestamp: (new Date).toISOString(),
context: {
...t,
entryPoint: t.entryPoint || a
}
};
var c;
return r instanceof Error && (o.error = {
name: r.name || "Error",
message: (r.message || "").slice(0, 500),
stack: r.stack ? (c = r.stack, c && "string" == typeof c ? c.replace(g, "[JWT]").replace(p, "[EMAIL]").replace(y, "").replace(_, "").slice(0, 2e3) : "") : void 0
}), o
}function w(e) {
e && "string" == typeof e.type && (o >= 100 || (n = [...n, e], o += 1, n.length >= 10 && k()))
}async function k() {
if (0 === n.length) return;
if (!await async function() {
return new Promise(e => {
try {
chrome.storage.local.get([r], t => {
chrome.runtime.lastError ? e(!0) : e(!1 !== t[r])
})
} catch {
e(!0)
}
})
}()) return void(n = []);
const t = await f(),
o = n.slice(0, 50);
n = n.slice(o.length), await async function(t) {
if (!t || 0 === t.length) return;
const r = l ? `${e}?dry_run=true` : e,
n = new AbortController,
o = setTimeout(() => n.abort(new DOMException("Request timed out", "TimeoutError")), 5e3);
try {
const e = await fetch(r, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
events: t.slice(0, 50)
}),
signal: n.signal
});
l && await async function(e, t) {
try {
const r = await t.json();
! function(e) {
if (0 === e.rejected) console.log("%c[BLN Dry Run] ALL ACCEPTED (%d/%d)", "color: #00b894; font-weight: bold;", e.accepted, e.total);
else {
console.warn("%c[BLN Dry Run] REJECTED %d/%d", "color: #d63031; font-weight: bold;", e.rejected, e.total);
for (const t of e.errors) console.warn(" [%d] %s: %s", t.index, t.field, t.error)
}
}(r);
const n = v(e, r);
u.push(n), u.length > 50 && (u = u.slice(-50)), await async function() {
const e = m();
if (e) try {
e.set({
[d]: u
})
} catch {
u = u.slice(-10);
try {
e.set({
[d]: u
})
} catch {}
}
}()
} catch (t) {
const r = t instanceof Error ? t.message : "unknown";
u.push(v(e, {
error: `Response parse failed: ${r}`
}))
}
}(t, e)
} catch (e) {
if (l) {
const t = e instanceof Error ? e.message : "unknown";
console.error("%c[BLN Dry Run] NETWORK ERROR: %s", "color: #d63031; font-weight: bold; font-size: 13px;", t)
}
} finally {
clearTimeout(o)
}
}(o.map(e => "pending" === e.sessionId ? {
...e,
sessionId: t
} : e))
}function U(e, t) {
try {
if (!e || "string" != typeof e || !A.has(e) || !N) return;
q += 1;
const r = (new Date).toISOString();
let n = "unknown";
try {
n = chrome.runtime.getManifest().version || n
} catch {}
w({
sessionId: "analytics",
extensionVersion: n,
chromeVersion: "n/a",
platform: M.platform,
locale: M.lang,
type: "analytics",
timestamp: r,
context: {
entryPoint: "background"
},
analyticsData: {
type: "analytics",
anon_id: L || "0000000000000000",
event: e,
props: t && "object" == typeof t ? {
...t
} : {},
user: {
...M
},
seq: q,
ts: r
}
})
} catch {}
}async function(e) {
if (e && !N) try {
N = !0, await async function() {
if (L) return L;
const e = (await O([I]))[I];
if ("string" == typeof e && 16 === e.length) return L = e, L;
let t = "unknown";
try {
t = chrome.runtime.id || t
} catch {}
const r = await O([D]);
let n = "string" == typeof r[D] && r[D] ? r[D] : "";
n || (n = String(Date.now()), await j({
[D]: n
}));
const o = new Uint8Array(await crypto.subtle.digest("SHA-256", (new TextEncoder).encode(t + "_" + n)));
let a = "";
for (let e = 0; e < o.length && a.length < 16; e++) a += o[e].toString(16).padStart(2, "0");
return L = a.slice(0, 16), await j({
[I]: L
}), L
}();
const t = await O([P]);
t[P] && "object" == typeof t[P] && (M = C(R, t[P])), x(e)
} catch {}
}("background")window.addEventListener("error", e => {
try {
e.filename && e.filename.includes(chrome.runtime.id) && _(e.error || new Error(e.message), {
domain: location.hostname
})
} catch (e) {}
})