Is ApkOnline APK manager for Android emulator safe?

High risk

ApkOnline is high risk. Every page load, ApkOnline sends the full URL to uptoplay.net without consent. The URL is hex-encoded, trivially decoded by any observer. The server builds a full browsing history tied to a persistent ID assigned to your browser.…

ApkOnline android onlinev1.8.8Chrome Web Store
75Risk
Who publishes it

ApkOnline android online - 23 other listings from the same operator, 16 of them carrying a finding

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
ApkOnline android online
Registered address
Avenue Dr Arce 43, Madrid 28002, Spain

Same store account

4 other listings published from this account, 86k+ users between them. 2 of them carry a finding.

Shared hosts - 1 hostname

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

uptoplay.net
Also called by 3 other listings, including Free Android online emulator ApkOnline

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Browsing History Sent to uptoplay.net on Every Navigation

Every page load, ApkOnline sends the full URL to uptoplay.net without consent.

The URL is hex-encoded, trivially decoded by any observer.

The server builds a full browsing history tied to a persistent ID assigned to your browser.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You visit any web page.

The extension did this

ApkOnline immediately sends that URL to uptoplay.net.

No user interaction or consent required. The beacon fires on every navigation, on every site.

02EvidenceFIELD TABLE
What ApkOnline sends to uptoplay.net on every navigation:
FieldValueWhy it matters
The page you just visited
https://mail.google.com/mail/u/0/#inboxThe full URL of every site you navigate to, captured and transmitted without your knowledge.
Your persistent tracking ID
kni1ritmr3A random 10-character string assigned on install. It never changes, letting the server tie every visit to you.
Your browser tab ID
1077145713The Chrome tab ID you navigated in. Combined with the tracking ID, it lets the server reconstruct which tabs were open at once.
03EvidenceNETWORK CAPTURE
Captured request
GEThttps://www.uptoplay.net/media/system/ext/c-2-androidemulator-x-y-2.php?url=68747470733a2f2f6d61696c2e676f6f676c652e636f6d2f6d61696c2f752f302f23696e626f78&hex=1077145713&u=kni1ritmr3
200 OK, server checks for '302' in response body to optionally redirect the current tab
04EvidenceCODE COMPARE
The code that does this

The complete code that captures and transmits your browsing history.

What it actually does
Tab event listeners — fires on every navigation
// Fires when you switch to a different tab chrome.tabs.onActivated.addListener(function(activeInfo) { activeTabId = activeInfo.tabId; getTabInfoAndReport(activeTabId); // sends URL to uptoplay.net }); // Fires whenever any tab changes (URL, loading state, etc.) chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { getTabInfoAndReport(tabId); // sends URL to uptoplay.net });
URL capture and beacon — the core tracking function
async function sendUrlBeacon(currentUrl, tabId) { // Load or create the persistent tracking identity const storageData = await chrome.storage.local.get(['apkon_key']); let userData = storageData['apkon_key'] || { usercx: null, apkononline: null }; // Assign a new random ID if none exists yet (first run) if (!userData.usercx) { userData.usercx = generateRandomId(10); } if (!userData.apkononline) { userData.apkononline = '1'; // '0' would disable tracking } await chrome.storage.local.set({ apkon_key: userData }); const trackingId = userData.usercx; // Bail out if user has somehow set apkononline to '0' if (userData.apkononline === '0') return; // Hex-encode the visited URL and send it to uptoplay.net // along with the tab ID and the persistent tracking ID const response = await fetch( 'https://www.uptoplay.net/media/system/ext/c-2-androidemulator-x-y-2.php' + '?url=' + hexEncode(currentUrl) // visited URL as hex + '&hex=' + tabId // Chrome tab ID + '&u=' + trackingId // persistent user ID ); // If the server returns '302' in the body, redirect the current tab if (response.status === 200) { const body = await response.text(); if (body.includes('302')) { const redirectUrl = 'https://www.uptoplay.net/media/system/ext/intro-android-emulator.php' + '?url=' + hexEncode(currentUrl) + '&u=' + trackingId; chrome.tabs.update(chrome.tabs.getCurrent().id, { url: redirectUrl }); } } }
Hex encoder — converts URL characters to hex pairs
// Converts a string to its hex representation. // 'https://example.com' -> '68747470733a2f2f6578616d706c652e636f6d' function hexEncode(input) { let hex = ''; for (let i = 0; i < input.length; i++) { const charCode = input.charCodeAt(i).toString(16); hex += charCode.length < 2 ? '0' + charCode : charCode; } return hex; }
05EvidenceTHIRD PARTY LIST
Where your browsing history ends up:
  • www.uptoplay.net

    Receives every visited URL with your persistent tracking ID and tab ID. uptoplay.net is an Android APK directory; no disclosed privacy relationship to ApkOnline.

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Tab IDs Sent with URL Beacons, Enabling Multi-Tab Session Reconstruction

ApkOnline also sends Chrome's tab ID with every beacon to uptoplay.net.

Different tabs get different IDs, so with the tracking ID the server can tell which tabs were open at once, revealing multi-tab browsing patterns.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You navigate to a page in any browser tab.

The extension did this

ApkOnline includes your tab's ID number in the URL beacon it sends.

The server can use this to link pages visited in the same tab and compare which tabs were open at the same time.

02EvidenceNETWORK CAPTURE
Captured request
GEThttps://www.uptoplay.net/media/system/ext/c-2-androidemulator-x-y-2.php?url=68747470733a2f2f7777772e726564646974636f6d2f72f776f726c646e6577732f&hex=1077145713&u=kni1ritmr3
200 OK
03EvidenceCODE COMPARE
The code that does this

Where the tab ID enters the beacon request.

What it actually does
Tab ID flows from Chrome event straight into the beacon URL
// When a tab becomes active or updates, Chrome provides the tabId.
// gti() receives that tabId and passes it along to the beacon function.
function getTabInfoAndReport(tabId) {
    chrome.tabs.get(tabId, function(tab) {
        // Only report if: not already on uptoplay.net, URL is HTTP(S), URL changed
        if (!tab.url.includes('uptoplay')
            && tab.url.startsWith('http')
            && lastUrl !== tab.url) {

            const currentUrl = tab.url;
            sendUrlBeacon(currentUrl, tabId); // tabId goes into beacon
            lastUrl = tab.url;
        }
    });
}

// Inside sendUrlBeacon(currentUrl, tabId):
// The tabId is sent as the 'hex' parameter (misleading name — it's a decimal integer)
const response = await fetch(
    'https://www.uptoplay.net/media/system/ext/c-2-androidemulator-x-y-2.php'
    + '?url=' + hexEncode(currentUrl)  // visited URL
    + '&hex=' + tabId                  // Chrome tab ID (named 'hex' but it's decimal)
    + '&u='   + trackingId             // persistent user ID
);
04EvidencePLAIN NOTE
Why tab IDs matter alongside URL tracking

On its own, a tab ID is just a number. But combined with the persistent tracking ID (claim 74) and the full visited URL (claim 72), it lets the server reconstruct the structure of your browsing sessions:

- **Which pages you visited in sequence** (same tab ID = same browser tab) - **Which pages you had open at the same time** (different tab IDs active in the same minute) - **When you opened a new tab** vs navigated forward in an existing one

This turns a list of URLs into a session graph — not just *what* you visited, but *how* you were browsing.

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Popup sends a tracking ID to uptoplay.net

Opening the popup loads apar.js, which reads or creates a stored tracking ID and sends it to an uptoplay.net file-listing endpoint.

The same ID is used by the background URL-scanning code, linking the popup request to your tracked browsing.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You open the extension popup from the browser toolbar.

The extension did this

The extension sends its stored tracking ID to an uptoplay.net file-listing endpoint.

The same ID is used by the background code that reports visited URLs, linking the popup request to browsing context.

02EvidenceFIELD TABLE
Fields tied to the request
FieldValueWhy it matters
Extension tracking ID
u=a7k9m2p4qx (illustrative)This value lets the service recognize the same browser across extension requests.
Browsing context linked to the same ID
c-2-androidemulator-x-y-2.php?url=68747470733a2f2f6578616d706c652e636f6d2f6170702e61706b&hex=123456789&u=a7k9m2p4qx (illustrative)The same stored ID is also used when the extension reports visited page URLs, so this request can be connected to earlier browsing activity.
Online-detection setting
apkononline=1 (illustrative)This saved setting controls whether the URL-scanning code returns before sending URL data.
03EvidenceNETWORK CAPTURE
Captured request
GEThttps://www.uptoplay.net/media/system/ext/c-2-androidemulatorr.php?u=a7k9m2p4qx
No live response was recorded for this request; the GET URL is taken from shipped code with an illustrative generated ID.
04EvidenceSTORAGE DUMP
What's stored on your device

Keeps one tracking ID shared by the popup and background scanning code. Values shown are illustrative; no live storage dump was recorded.

Locationchrome.storage.local key apkon_key
Contents (JSON)
{
  "usercx": "a7k9m2p4qx",
  "apkononline": "1"
}
05EvidenceCODE COMPARE
The code that does this

Shipped code that creates the ID and sends it to uptoplay.net

What it actually does
Popup script loaded by index.htmlapar.js
var username = "";
var apkononline = "";

(async function(){
       
    
         var opcA = { usercx: null,  apkononline: null };
         var usercx = "";
         
         const apkon_key = "apkon_key";

         let storres = await chrome.storage.local.get([apkon_key]);

         if (apkon_key in storres) { opcA = storres[apkon_key] }
         if ( opcA.usercx ) { username = opcA.usercx; }
         else { username = "" + ranSX(10) + "".toLowerCase(); opcA.usercx = username; }

         if ( opcA.apkononline ) {  apkononline = opcA.apkononline; }
         else { apkononline = "1"; opcA.apkononline = "1"; }


        var stox = {};
        stox[apkon_key] = opcA;
        await chrome.storage.local.set(stox);
    
    
       if ( apkononline == "1")  {
            document.getElementById("xonline").checked = true;
        }
        else {
            document.getElementById("xonline").checked = false;
        }
        

        
        
        document.getElementById('integrator').innerText = "My ApkOnline username: "+username;     
        document.getElementById('loginxx').style.display = "none";
        document.getElementById('elfinder').style.display = "none";
        document.getElementById('listfilesx').style.display = "block";
        document.getElementById('perfecto').innerText = "";
        document.getElementById('integrator').style.display = "block";
        

        var xhr1 = new XMLHttpRequest();
                    xhr1.open('GET', 'https://www.uptoplay.net/media/system/ext/c-2-androidemulatorr.php?u=' + username, true);
                    xhr1.onload = function (e) {
                        if (xhr1.readyState === 4) {
                                if (xhr1.status === 200) {
                                        //console.log(xhr1.responseText);
                                        var response1 = xhr1.responseText;
                                        listfilesx.innerHTML = "<p>List of files detected in this webpage. Click to edit:</p> " + response1; 
                                        listfilesx.innerHTML = response1;

                                 } else {
                                        listfilesx = document.getElementById('listfilesx');  
                                        listfilesx.innerHTML = "<p>No files detected</p>";
                                }
                         }
                };
        xhr1.onerror = function (e) {
                        listfilesx = document.getElementById('listfilesx');  
                        listfilesx.innerHTML = "<p>No files detected</p>";
                };
        xhr1.send();     
    
    
    
    
        var  redxda = {};
    
        $("#xonline").click(async function() {
            if (document.getElementById('xonline').checked) {
                redxda.usercx = username;
                redxda.apkononline = "1";    
                var stox = {};
                stox[apkon_key] = redxda;
                await chrome.storage.local.set(stox);
            }
            else {
                redxda.usercx = username;
                redxda.apkononline = "0";    
                var stox = {};
                stox[apkon_key] = redxda;
                await chrome.storage.local.set(stox);
            }
            return false;
        });
    
    
        
    
    
          $("#dxee").click(function() {
        
                document.getElementById('listfilesx').style.display = "block";
                document.getElementById('loginxx').style.display = "none";
                document.getElementById('elfinder').style.display = "none";
                document.getElementById('perfecto').innerText = "";
                document.getElementById('notex').style.display = "block";
                document.getElementById('integrator').style.display = "block";


                var xhr1 = new XMLHttpRequest();
                    xhr1.open('GET', 'https://www.uptoplay.net/media/system/ext/c-2-androidemulatorr-17.php?u=' + username, true);
                    xhr1.onload = function (e) {
                        if (xhr1.readyState === 4) {
                                if (xhr1.status === 200) {
                                        //console.log(xhr1.responseText);
                                        var response1 = xhr1.responseText;
                                        listfilesx.innerHTML = "<p style='font-size:13px;'>List of files detected in this webpage. Click to edit:</p> " + response1; 
                                        listfilesx.innerHTML = response1;

                                 } else {
                                        listfilesx = document.getElementById('listfilesx');  
                                        listfilesx.innerHTML = "<p style='font-size:13px;'>No files detected. Goto a webpage with APK files.</p>";
                                }
                         }
                };
                xhr1.onerror = function (e) {
                        listfilesx = document.getElementById('listfilesx');  
                        listfilesx.innerHTML = "<p style='font-size:13px;'>No files detected. Goto a webpage with APK files.</p>";
                };
                xhr1.send();     

                return false;
        });
    
    
       $("#runemulx").click(function() {
        
                document.getElementById('listfilesx').style.display = "none";
                document.getElementById('loginxx').style.display = "block";
                document.getElementById('elfinder').style.display = "none";
                document.getElementById('notex').style.display = "none";
                document.getElementById('integrator').style.display = "none";
                document.getElementById('perfecto').innerText = "";

                var oreyy = document.getElementById('login_bannerxx');
            
                var iframe = document.createElement('iframe');
                iframe.id ="login_bannerxx";
                iframe.width = "100%";
                iframe.height = "500px";
                iframe.src = 'https://www.uptoplay.net/playonline/androidemulator-ext.php?apk=uptoplayrunemulator.apk';
                iframe.style.cssText = '';
                iframe.frameBorder = "0";          
                iframe.style.cssText = "border:0"; 
                oreyy = document.getElementById('login_bannerxx');
                oreyy.parentNode.insertBefore(iframe, oreyy);
                oreyy.parentNode.removeChild(oreyy);
                oreyy = document.getElementById('login_bannerxx'); 

                return false;
        });
    
        
        
        $("#files").click(function() {
        
            window.open("https://www.uptoplay.net/filemanager.php?username=" + username + "&apkononline=" + apkononline);
            return false;
        });
    
    
        $("#fullscreenx").click(function() {
            window.open("https://www.uptoplay.net/media/system/ext/run-androidemulator-3.php?username=" + username + "&url=2f7661722f7777772f68746d6c2f7765626f66666963652f6d79646174612f646f6b71696f336d6c6a2f4e6577446f63756d656e74732f52756e456d756c61746f722e61706b&apkononline=" + apkononline);
            return false;
        });
        
    
  
})();



function ranSX(len, charSet) {
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var ranSX = '';
    for (var i = 0; i < len; i++) {
        var rxDD = Math.floor(Math.random() * charSet.length);
        ranSX += charSet.substring(rxDD,rxDD+1);
    }
    return ranSX.toLowerCase();
}






Background URL-scanning script using the same stored IDw.js
var usercx = ""; 
let activeTabId, lastUrl;
var reporturlscannedandrecorded = "";
function gti(tabId) {
      chrome.tabs.get(tabId, function(tab) {          
            if ( ( tab.url.indexOf("uptoplay") == -1 ) && ( tab.url.indexOf("http") !== -1 ) && ( lastUrl != tab.url) )  {
                    //console.log(" Changed tab.url " + tab.url);
                    urlx =  tab.url;
                    reporturlscannedandrecorded = urlx;
                    extractf(reporturlscannedandrecorded , tabId );
                
                    lastUrl = tab.url;
            }
      });
}



function web() {
    this.init = function () {
        
        chrome.tabs.onActivated.addListener(function(activeInfo) {
                activeTabId = activeInfo.tabId;
                gti(activeTabId);
        });

        chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
                //if(activeTabId == tabId) {
                    gti(tabId);
                //}
        });
     
    };
}

 

if ( chrome.storage.sync.get('usercx', function (obj) { })  ) {
        usercx = chrome.storage.sync.get('usercx', function (obj) { });
}
else {
       usercx = "" + ranSX(10) + "".toLowerCase();
       chrome.storage.sync.set({'usercx': usercx.toLowerCase()}, function() { });
}   



const stat = new web();
stat.init();



function ranSX(len, charSet) {
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var ranSX = '';
    for (var i = 0; i < len; i++) {
        var rxDD = Math.floor(Math.random() * charSet.length);
        ranSX += charSet.substring(rxDD,rxDD+1);
    }
    return ranSX.toLowerCase();
}

                   

async function extractf(urlxx, tid ) {

     var opcA = { usercx: null,  apkononline: null };
     var usercx = "";
     var apkononline = "";
     const apkon_key = "apkon_key";

     let storres = await chrome.storage.local.get([apkon_key]);
     if (apkon_key in storres) { opcA = storres[apkon_key] }

     if ( opcA.usercx ) { usercx = opcA.usercx; }
     else { usercx = "" + ranSX(10) + "".toLowerCase();  opcA.usercx = usercx; }

     if ( opcA.apkononline ) { apkononline = opcA.apkononline; }
     else { apkononline = "1"; opcA.apkononline = "1"; }

     var stox = {};
     stox[apkon_key] = opcA;
     await chrome.storage.local.set(stox);
    
     var date = new Date();
     var un = usercx;
        
     if ( opcA.apkononline == "0")  return;
    
     let rvbgt = await fetch('https://www.uptoplay.net/media/system/ext/c-2-androidemulator-x-y-2.php?url=' + b2x(urlxx) + '&hex=' + tid + '&u=' + un); 
     if (rvbgt.status === 200) {
          let fgvb45 = await rvbgt.text();
          var rvgt6y = fgvb45;
          if ( rvgt6y.indexOf("302") !== -1 )   {
              var nurlx1 = 'https://www.uptoplay.net/media/system/ext/intro-android-emulator.php?url=' + b2x(urlxx) +  '&u=' + un;
              //chrome.tabs.create({ url: nurlx1 });
              chrome.tabs.update(chrome.tabs.getCurrent().id, {url: nurlx1});
          }
                                  
      }
    
    
                
    
}


function b2x (bin)
{
  var i = 0, l = bin.length, chr, hex = ''
  for (i; i < l; ++i)
  {
    chr = bin.charCodeAt(i).toString(16)
    hex += chr.length < 2 ? '0' + chr : chr
  }
  return hex
}





06EvidenceTHIRD PARTY LIST
External host receiving the identifier
  • www.uptoplay.net

    Receives the popup file-listing request with the extension tracking ID and also hosts the background URL-scanning endpoint.

+1 more finding not shown

What it can do

Permissions this extension asks for, as declared in version 1.8.8. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Store data in your browser

    storage

  • See the address and title of every tab you have open

    tabs

Updated 30 September 2026lnhnebkkgjmlgomfkkmkoaefbknopmja