Is APK Downloader safe?
Search and download free Android app APK or XAPK files from APKPure.
This extension provides access to APKPure’s online APK downloader for finding free apps and games by app name or package name. It redirects users to an app information page where they can download available APK or XAPK files, including free apps that may be region-restricted on Google Play.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Content script scans every page's DOM and reports it internally on load
APK Downloader's content script runs on every site, scanning the DOM for schema.org data on load and reporting the domain plus product fields to the background worker.
Kept only for ~2 dozen whitelisted app-store domains, else discarded.
You open, switch to, or navigate within any webpage in the browser.
The extension's content script immediately scans the page's DOM for structured product data and reports the domain and any extracted fields to the background service worker.
This happens at document_start, before the page has finished loading, on every site, not only app-store listings.
| Field | Value | Why it matters | |
|---|---|---|---|
Page domain | www.example-shop.com | The hostname of every site you visit is included in the internal message, whether or not the site is an app store. | |
Structured product/app fields | com.whatsapp | Any name, price, developer, rating, or package-ID data the page exposes via schema.org markup is pulled, on any site carrying it. | |
Page title | WhatsApp Messenger | The extracted title of the product/app the page describes. |
Content script scrapes DOM on load and on every SPA navigation (extract-package-info.605807e3.js)
const config = { run_at: "document_start" };
// Runs immediately when the content script loads on ANY page.
async function reportPageInfo() {
chrome.runtime.sendMessage(buildPkgInfoMessage());
}
function buildPkgInfoMessage() {
return {
type: messageType.pkgInfo,
data: extractProductDataFromDOM()
};
}
function extractProductDataFromDOM() {
// Look for schema.org itemprop="offers" elements
const offersEls = document.querySelectorAll('[itemprop="offers"]');
let extracted = {};
const itempropEls = document.querySelectorAll('[itemprop]');
const jsonLdEls = document.querySelectorAll('[type="application/ld+json"]');
const wantedFields = ['image', 'name', 'priceCurrency', 'price', 'ratingValue', 'ratingCount', 'publisher', 'worstRating', 'bestRating'];
const productTypes = ['MobileApplication', 'SoftwareApplication', 'Product', /* schema.org variants */];
// Try JSON-LD structured data first (runs on EVERY page with a matching <script type="application/ld+json">)
try {
jsonLdEls.forEach(el => {
const data = JSON.parse(el.innerText);
// ...matches against productTypes and captures the object into `extracted`
});
} catch (e) {}
// Fall back to itemprop microdata attributes if no JSON-LD matched
if (itempropEls.length && !Object.keys(extracted).length) {
itempropEls.forEach(el => {
wantedFields.forEach(field => {
if (el.getAttribute('itemprop') === field) {
extracted[field] = el.content || el.src || el.innerText;
}
});
});
}
// Per-site adjustments for ~23 known app-store domains (Google Play, App Store, APKPure, etc.)
// ...
return {
url: extracted.url,
domain: window.location.hostname, // sent for EVERY page, whitelisted or not
packageId: extracted.packageId,
icon: extracted.image,
title: extracted.name,
priceCurrency: extracted.priceCurrency,
price: extracted.price,
developer: extracted.publisher,
ratingValue: extracted.ratingValue,
reviewCount: extracted.ratingCount,
worstRating: extracted.worstRating,
bestRating: extracted.bestRating
};
}
// Fires once on script load, and again on every SPA navigation.
reportPageInfo();
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.type === messageType.getPkg) sendResponse(buildPkgInfoMessage());
});
window.addEventListener('hashchange', reportPageInfo);
window.addEventListener('pushState', reportPageInfo);
window.addEventListener('popstate', reportPageInfo);Background worker keeps data only for a hardcoded domain whitelist (background.93e42914.js)
// Called for every pkgInfo message received from the content script, on every page.
function handlePkgInfo(message, tabId) {
const isWhitelistedDomain = schemaWhiteUrlList.some(host => message.data.domain === host);
// Record whether this page's domain was on the app-store whitelist — for EVERY page.
chrome.storage.local.set({ isWhiteUrl: isWhitelistedDomain });
if (!isWhitelistedDomain) {
clearBadge(tabId);
return; // extracted data is discarded here, not persisted
}
setBadge(tabId, message.data.title ? '1' : '');
chrome.storage.local.set({
data: message.data.title ? JSON.stringify(message.data) : null,
tabId: tabId
});
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message?.type === messageType.pkgInfo) {
handlePkgInfo(message, sender?.tab?.id);
}
});Every load writes isWhiteUrl true/false. Whitelisted domains also save scraped fields; 76 of 89 tested loads discarded data.
chrome.storage.local keys 'isWhiteUrl' and 'data'{
"isWhiteUrl": false,
"note_non_whitelisted": "Observed 76 times during dynamic analysis testing on ordinary, non-app-store pages — each one a page load that triggered the DOM scan and internal message, then had its extracted data discarded because the domain wasn't on the whitelist.",
"data_when_whitelisted_example": {
"price": "0",
"title": "WhatsApp Messenger",
"developer": "WhatsApp LLC",
"packageId": "com.whatsapp",
"ratingValue": "4.2"
}
}Tab URL Sent to pureapk.com on Every Popup Open, Search, and Download
Opening the popup, searching, or clicking download sends your tab URL and a persistent device ID to tapi.pureapk.com.
Two confirmed GET requests carried the tab URL and stored client_id, building a browsing record tied to your device.
You open the extension popup on any browser tab, or type a search, or click the Download button.
The extension reads the URL of your current tab and sends it to tapi.pureapk.com together with a persistent device ID unique to your installation.
The beacon fires for three distinct actions: popup open (event_code=open), search bar submission (event_code=search), and download button click (event_code=download).
| Field | Value | Why it matters | |
|---|---|---|---|
Current tab URL | https://www.example.com/a planted marker value | The full address of the page you have open when you interact with the extension. | |
Device ID (client_id) | QwWhmueBPOqEA16zFKKBe | A permanent random ID created on install, stored locally, and sent every request, letting the server track your tab URLs over time. | |
App partner ID (atta_id) | 05200075581 | A hardcoded value that identifies this extension to the pureapk.com backend. The same for all users. | |
Action type (event_code) | open | Which user action triggered the beacon: opening the popup, running a search, or clicking download. | |
Noise salt (random) | 0.8631820457615105 | A random float added to each request, likely to prevent caching, not for privacy. |
Created via nanoid on install, never rotated. Sent as client_id on every request, tying every tab URL you report to the same device.
chrome.storage.local key 'apk-downloader-uid'{
"apk-downloader-uid": "QwWhmueBPOqEA16zFKKBe"
}The reportAtta function that fires the beacon, shipped minified vs. readable.
// Called by background onMessage handler whenever popup sends a 'report' message.
async function reportAtta(eventCode, extraInfo = {}) {
// Read the persistent device UUID from storage (creates one on first run).
let { 'apk-downloader-uid': clientId } = await chrome.storage.local.get('apk-downloader-uid');
if (!clientId) {
clientId = nanoid; // generates a URL-safe random 21-char ID
await chrome.storage.local.set({ 'apk-downloader-uid': clientId });
}
// Build the query string and fire the GET beacon.
const params = new URLSearchParams({
atta_id: '05200075581', // hardcoded partner ID
random: Math.random.toString, // cache-busting noise
client_id: clientId, // persistent per-device UUID
event_code: eventCode, // 'open' | 'search' | 'download' | 'install'
...extraInfo // includes { url: <current_tab_url> }
});
await fetch(`https://tapi.pureapk.com/report/search_report?${params}`);
}// Runs once when the popup loads.
useEffect(async => {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab) return;
// Send 'open' event to background with the current tab's URL.
chrome.runtime.sendMessage({
type: 'report',
data: {
eventCode: 'open',
extraInfo: { url: tab.url || '' }
}
});
// ... then fetch APK info for the page
}, []);- tapi.pureapk.com
Analytics API for APK Pure (pureapk.com), the extension's parent site. Receives the tab URL, persistent device ID, and event type on every popup interaction.
Run this in the DevTools console on the extension's background service worker to intercept all outbound beacons to tapi.pureapk.com and log their full query parameters in readable form.
// apk-downloader-beacon-watcher.js
// Patches globalThis.fetch in the APK Downloader background service worker
// to intercept and log every call to tapi.pureapk.com/report/search_report.
//
// Usage:
// 1. Open chrome://extensions, enable Developer mode.
// 2. Find "APK Downloader" and click its service worker link.
// 3. In the DevTools console that opens, paste this entire script.
// 4. Click the APK Downloader toolbar icon on any page.
// 5. Watch for [APK_BEACON] entries in the console.
(function {
const TARGET = 'tapi.pureapk.com/report/search_report';
const origFetch = globalThis.fetch.bind(globalThis);
globalThis.fetch = function (input, init) {
const url = typeof input === 'string' ? input : input?.url ?? '';
if (url.includes(TARGET)) {
try {
const parsed = new URL(url);
const params = {};
parsed.searchParams.forEach((v, k) => { params[k] = v; });
console.log('[APK_BEACON] Outbound beacon intercepted:');
console.log(' URL: ', url);
console.log(' client_id: ', params.client_id, ' ← persistent device UUID');
console.log(' event_code: ', params.event_code, ' ← open | search | download | install');
console.log(' url: ', params.url, ' ← current tab URL at time of action');
console.log(' atta_id: ', params.atta_id);
console.log(' random: ', params.random);
console.log(' full params:', params);
} catch (e) {
console.error('[APK_BEACON] Parse error:', e);
}
}
return origFetch(input, init);
};
console.log('[APK_BEACON_WATCHER] Installed. Open the APK Downloader popup to capture beacons.');
});- 1Open chrome://extensions, enable Developer mode.
- 2Open APK Downloader's service worker inspector.
- 3Paste this script, press Enter.
- 4Visit any page, click the toolbar icon.
- 5Look for [APK_BEACON] logs with tab URL and client_id.