Created
July 13, 2026 19:37
-
-
Save absurd/ea6e7fa70313919d676509ad4a542203 to your computer and use it in GitHub Desktop.
XCancel Firefox verification workaround
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name XCancel Firefox verification workaround | |
| // @namespace local.xcancel.workaround | |
| // @version 1.0.0 | |
| // @description Work around XCancel's fragile screen/viewport verification check in Firefox. | |
| // @match https://xcancel.com/* | |
| // @run-at document-start | |
| // @sandbox raw | |
| // @grant none | |
| // @noframes | |
| // ==/UserScript== | |
| (() => { | |
| "use strict"; | |
| // XCancel only attaches one of its per-request verification headers when | |
| // screen.width/height exactly match the page's inner viewport. Firefox UI | |
| // such as the revamped sidebar can make those values differ. Present the | |
| // viewport dimensions through Screen until the verification page has run, | |
| // so XCancel's own script supplies the current challenge header and value. | |
| const prototype = Screen.prototype; | |
| const originalWidth = Object.getOwnPropertyDescriptor(prototype, "width"); | |
| const originalHeight = Object.getOwnPropertyDescriptor(prototype, "height"); | |
| let installed = false; | |
| const viewportWidth = () => | |
| window.innerWidth || document.documentElement?.clientWidth || 0; | |
| const viewportHeight = () => | |
| window.innerHeight || document.documentElement?.clientHeight || 0; | |
| const restore = () => { | |
| if (!installed) return; | |
| try { | |
| Object.defineProperty(prototype, "width", originalWidth); | |
| Object.defineProperty(prototype, "height", originalHeight); | |
| } finally { | |
| installed = false; | |
| } | |
| }; | |
| try { | |
| if (!originalWidth?.configurable || !originalHeight?.configurable) { | |
| throw new Error("Screen dimension properties are not configurable"); | |
| } | |
| installed = true; | |
| Object.defineProperty(prototype, "width", { | |
| configurable: true, | |
| enumerable: originalWidth.enumerable, | |
| get: viewportWidth, | |
| }); | |
| Object.defineProperty(prototype, "height", { | |
| configurable: true, | |
| enumerable: originalHeight.enumerable, | |
| get: viewportHeight, | |
| }); | |
| } catch (error) { | |
| restore(); | |
| console.warn("[XCancel workaround] Could not patch screen dimensions:", error); | |
| return; | |
| } | |
| // On a successful reload, restore the native Screen implementation as soon | |
| // as ordinary XCancel content is identified. Keep the patch active on the | |
| // verification document because its challenge runs shortly after DOM load. | |
| const restoreOnContentPage = () => { | |
| if (!/Verifying your request/i.test(document.title)) { | |
| restore(); | |
| } | |
| }; | |
| if (document.readyState === "loading") { | |
| document.addEventListener("DOMContentLoaded", restoreOnContentPage, { | |
| once: true, | |
| }); | |
| } else { | |
| restoreOnContentPage(); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment