Greasy Fork is available in English.

Diskusie » Vývoj

Capturing media files from XHR

Pridaný: 30.05.2023
Upravený: 30.05.2023


Me and my friends have made a script that fetches media from DOM, but capturing media from XHR was not handled yet.

As more and more websites send media from XHR it is important for us to begin working on capturing media from XHR.

Please help or even join us.

Thank you

Pridaný: 30.05.2023

Use PerformanceObserver.

Pridaný: 31.05.2023

What's the point? There are some browser extensions to capture media existing already. Are they bad?

Konf, yes this is true.


  • Not all browsers have access to extensions.
  • Most browsers support userscripts.
  • Regardless to the above, capturing media is needed for Tobacco Cinema so video be displayed.

In order to avoid script execution, ads and any other distraction, Tobacco Cinema is loded immediately (it is set to run at document-start), so it is not possible to copy an object or video element because the original page has never been loaded.

  • It might be possible by parsing the document, yet it might involve unwanted scripts which would cause to unwanted popups and ads.

The purpose of Tobacco Cinema is to avoid distractions so user won't be enticed to watch another video and hopefully find a nice lady (or gentlemen, if user is a woman) to get married.

This is why this thread was started.

Pridaný: 01.06.2023

I've made an example of any requests interception. I'm not sure that is what you need or if it works with browsers without access to extensions, but here you are:

// ==UserScript==
// @name          xhrs intercept example
// @description   xhrs intercept example
// @author        Konf
// @namespace
// @version       -1
// @match         *://*/*
// @run-at        document-start
// @grant         unsafeWindow
// ==/UserScript==

(function() {
  'use strict';

  const IDS_LENGTH = 6; // should be replaced to uuid

  const oldFetch = unsafeWindow.fetch;
  const oldXMLHttpRequest = unsafeWindow.XMLHttpRequest;

  // these should never throw an error, use try..catch somewhere
  const hooks = {
    fetch: {
      handleArgs: (fetchId, args) => {
        console.log(`fetch: args of ${fetchId}`, args);

      handleResult: (fetchId, response) => {
        console.log(`fetch: result of ${fetchId}`, response);

    xhr: {
      handleArgs: (xhrId, args) => {
        console.log(`xhr: args of ${xhrId}`, args);

      handleResult: (xhrId, onloadEvent, xhr) => {
        console.log(`xhr: result of ${xhrId}`, xhr);

  unsafeWindow.fetch = function(...args) {
    const fetchPromise = oldFetch(...args);
    const id = makeId(IDS_LENGTH); // should be replaced to uuid

    hooks.fetch.handleArgs(id, args);
    fetchPromise.then(r => hooks.fetch.handleResult(id, r));

    return fetchPromise;

  unsafeWindow.XMLHttpRequest = function(...args) {
    const xhr = new oldXMLHttpRequest();
    let xhrOpen =;
    let xhrOnload;

    const id = makeId(IDS_LENGTH); // should be replaced to uuid

    xhr.onload = (ev) => {
      hooks.xhr.handleResult(id, ev, xhr);
      if (xhrOnload) return xhrOnload(...args);

    Object.defineProperty(xhr, 'onload', {
      get: () => xhrOnload,
      set: (value) => (xhrOnload = value),

    Object.defineProperty(xhr, 'open', {
      get() {
        return (...args) => {
          hooks.xhr.handleArgs(id, args);
          return xhrOpen(...args);

      set: (value) => (xhrOpen = value),

    return xhr;

  // utils ---------------------------------------------------

  // should be replaced to uuid
  function makeId(length) {
    const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    let id = "";

    for (let i = 0; i < length; i++) {
      id += chars.charAt(Math.floor(Math.random() * chars.length));

    return id;

Pridať odpoveď

Aby ste mohli pridať odpoveď, prihláste sa.