Is Screenshot YouTube Video safe?

Medium risk

Screenshot YouTube Video sends the current page URL and a persistent browser ID to api.videodlservice.com daily.

Screenshot YouTube Video runs a content script on every website and, once per day, sends an analytics event from the page. That event includes the current page URL, extension version details, service metadata, and a persistent generated browser identifier stored by the extension.

uScreenshoterv0.7.69.0Chrome Web Store
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Daily Page URL Report to videodlservice Analytics

Screenshot YouTube Video sends a daily analytics POST from a normal page load to api.videodlservice.com, including the event name, a persistent browser identifier, and the current URL, linking a visit to example.com to that identifier.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You open a normal web page while the extension is installed.

The content script is configured for all HTTP and HTTPS pages and runs at the start of the document.

The extension did this

The extension can send a daily analytics event containing that page's URL.

In dynamic analysis, the event for https://www.example.com/ was posted to api.videodlservice.com with a persistent browser identifier.

02EvidenceNETWORK CAPTURE
Captured request
POSThttps://api.videodlservice.com/stat/
Observed during dynamic analysis as a request to the analytics endpoint.
Headers
Content-Typeapplication/json; charset=utf-8
Body
action=extension_daily hid=ec9db9e2-7915-4b2c-a08c-15d6ed87e08e media_source=https://www.example.com/.
03EvidenceFIELD TABLE
Fields observed in the daily analytics event
FieldValueWhy it matters
Daily event name
extension_dailyShows that the request is the extension's once-per-day analytics event rather than a download action you initiated.
Browser identifier
ec9db9e2-7915-4b2c-a08c-15d6ed87e08eLets the service connect separate daily reports from the same browser profile over time.
Current page URL
https://www.example.com/Shows the page open in your tab when the daily event is created, including any path or query text in that URL.
04EvidenceCODE COMPARE
The code that does this

The shipped code that schedules and sends the daily URL report

What it actually does
Persistent hid storage keydeobfuscated/content_script.js
const hid_defaultValue = esm_browser_v4();
const hid_name = "hid";

const hid_migrations = {
  name: hid_name,
  ups: [
    {
      v: 1,
      up: (storage, currentValue) => {
        if (typeof currentValue !== "string") {
          return storage.set(hid_name, hid_defaultValue);
        }
        return null;
      },
    },
  ],
};
Analytics body builderdeobfuscated/content_script.js
const getSendEvent = store => (
  async (data) => {
    const {
      defaultItem,
      hid,
      serviceName,
      utm,
    } = store.getState();
    const defData = {
      branch: config.branch,
      hash: config.hash,
      hid,
      project: config.extType,
      type: config.analyticsType,
      version: config.version,
      ...utm,
      format: defaultItem ? defaultItem.quality : "",
      media_source: window.location.href,
      service: serviceName,
      // format_high: "MAX_QUALITY"
    };
    try {
      const headers = [["Content-Type", "application/json; charset=utf-8"]];
      const body = JSON.stringify({ ...defData, ...data });
      network_sendPost(config.analyticsUrl, headers, body, true);
    } catch (e) {}
  }
);
Daily timer and default-service calldeobfuscated/content_script.js
/* harmony default export */ const send_daily = (async (sendEvent) => {
  const lastLoaded = await index_ext.get("extensionLoaded");
  if (!lastLoaded || (Date.now() - lastLoaded > 24 * 60 * 60 * 1000)) {
    index_ext.set("extensionLoaded", Date.now());
    sendEvent({ action: "extension_daily" });
  }
});

const checkServices = async () => {
  console.log("check services");

  inject_script(document, "patch-xhr.js", {});
  const timeoutId = setTimeout(() => {
    try {
      inject_script(document, "set-global.js", { name: "__stopWatching", value: true });
      inject_script(document, "set-global.js", { name: "__jsons", value: [] });
    } catch {}
  }, 5000);

  const modules = integration_modules();
  const modulesNames = Object.keys(modules);
  let uninstallObserver;

  /* eslint-disable no-await-in-loop */
  for (let i = 0; i < modulesNames.length; i++) {
    const moduleName = modulesNames[i];
    const module = modules[moduleName];
    const { isServiceUrl, Service } = module;
    if (isServiceUrl(window.location.href)) {
      if (!uninstallObserver) {
        uninstallObserver = true;
        const uninstallSelf = () => window.location.reload();
        addListener("uninstallSelf", uninstallSelf);
      }
      console.log("We've got a hit!!!", moduleName);
      clearTimeout(timeoutId);
      const store = await content_script_store(moduleName);

      const {
        eventRouter,
        setModule,
        setServiceName,
      } = store.getState();

      setModule(module);

      const service = new Service(eventRouter);
      setServiceName(service.serviceName);
      service.start();
    }
  }
  /* eslint-enable no-await-in-loop */
  // send daily even if there is no module to engage
  const defaultStore = await content_script_store("defaultService");
  const { sendEvent } = defaultStore.getState();
  send_daily(sendEvent);
};
Content script startupdeobfuscated/content_script.js
const start = async () => {
  if (!in_iframe()) {
    set_info();
  }

  // start default service anyway
  default_service.start();

  const onContentLoaded = () => {
    const alreadyStarted = check_if_injected();
    if (alreadyStarted) return;
    check_services();
  };
  if (document.readyState !== "loading") {
    onContentLoaded();
  } else {
    document.addEventListener("DOMContentLoaded", () => {
      onContentLoaded();
    }, false);
  }
};
05EvidenceTHIRD PARTY LIST
External destination receiving the daily event
  • api.videodlservice.com

    Receives the daily analytics POST containing the event name, persistent browser identifier, and current page URL.

What it can do

Permissions this extension asks for, as declared in version 0.7.69.0. 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

    http://*/*

  • Read and change your data on every secure site you visit

    https://*/*

  • Store data in your browser

    storage

  • Store an unlimited amount of data in your browser

    unlimitedStorage

Where it sends data

Destinations our analysis observed Scr YT Video contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.

  • api.videodlservice.com

    Scr YT Video sends data to api.videodlservice.com. 2 other extensions we have analysed send data here.

Updated 30 September 2026lnaahdmijnjnmgaalacdgakieangpjgp