Created
November 14, 2025 23:50
-
-
Save divinity76/a645b68047b79668f7b75531b47303ac to your computer and use it in GitHub Desktop.
Cloudflare admin token generator.js
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
| // for use on "Account API Tokens" -> "Create Custom Token", | |
| // https://dash.cloudflare.com/<uid>/api-tokens | |
| function injectJQuery() { | |
| // Avoid double-injecting | |
| if (window.jQuery || document.getElementById("jqueryElement")) return; | |
| let xhr = new XMLHttpRequest(); | |
| xhr.open("GET", "https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js", false); | |
| xhr.send(); | |
| const script = document.createElement("script"); | |
| script.id = "jqueryElement"; | |
| script.text = xhr.responseText; | |
| document.documentElement.appendChild(script); | |
| } | |
| injectJQuery(); | |
| // Dispatch mousedown, then mouseup to simulate a full click, | |
| // using absolute x/y coordinates.. | |
| // https://stackoverflow.com/a/79096035/1067003 | |
| function simulateMouseClick(element) { | |
| if (!element) { | |
| throw new Error('simulateMouseClick: Provided element is null or undefined.'); | |
| } | |
| const rect = element.getBoundingClientRect(); | |
| const x = rect.left + (rect.width / 2); | |
| const y = rect.top + (rect.height / 2); | |
| const targetWindow = (typeof unsafeWindow === 'undefined') ? window : unsafeWindow; | |
| const targetElement = document.elementFromPoint(x, y) || element; | |
| const eventOptions = { | |
| view: targetWindow, | |
| bubbles: true, | |
| cancelable: true, | |
| clientX: x, | |
| clientY: y | |
| }; | |
| ['mousedown', 'mouseup', 'click'].forEach(eventType => { | |
| targetElement.dispatchEvent(new MouseEvent(eventType, eventOptions)); | |
| }); | |
| } | |
| function pressAddMore() { | |
| $("span:contains(Add more):first").click(); | |
| setTimeout(selectAccountOrZone, 1); | |
| } | |
| function selectAccountOrZone() { | |
| if (selectAccountOrZone.target) { | |
| if (selectAccountOrZone.step !== 2) { | |
| selectAccountOrZone.step = 2; | |
| $("[data-testid=api_token_resources]:last button").click(); | |
| setTimeout(selectAccountOrZone, 1); | |
| } else { | |
| delete selectAccountOrZone.step; | |
| $("li:contains(" + selectAccountOrZone.target + "):last").click(); | |
| setTimeout(openSelectItem, 1); | |
| } | |
| } else { | |
| // if there was more than 1 option, we would do: selectAccountOrZone.target = "Account"; | |
| // here, but Account is the default and there is only 2 options, so it's a speed hack to | |
| // not select Account explicitly. | |
| // we don't even need to wait for DOM update in this case. | |
| openSelectItem(); | |
| } | |
| } | |
| function openSelectItem() { | |
| let eles = $("[id*=cf-form-input]:contains(Select item)"); | |
| eles[eles.length - 2].click(); | |
| if (openSelectItem.justMovedZone) { | |
| // need to wait for DOM update after changing from Account to Zone | |
| delete openSelectItem.justMovedZone; | |
| setTimeout(openSelectItem, 2000); // not sure why but after first zone switch, we need to click 2 times on "Select item" and be slow about it... | |
| } else { | |
| setTimeout(selectNextItem, 1); | |
| } | |
| } | |
| function selectNextItem() { | |
| let options = $("li[role=option]"); | |
| let nextIndex; | |
| if (selectNextItem.lastItemIndex !== undefined) { | |
| nextIndex = selectNextItem.lastItemIndex + 1; | |
| } else { | |
| nextIndex = 0; | |
| } | |
| if (nextIndex >= options.length) { | |
| if (selectAccountOrZone.target !== "Zone") { | |
| openSelectItem.justMovedZone = true; | |
| console.log("Account is finished! Moving on to Zone selection."); | |
| selectAccountOrZone.target = "Zone"; | |
| delete selectNextItem.lastItemIndex; | |
| setTimeout(selectAccountOrZone, 1); | |
| return; | |
| } | |
| console.log("no more items to select"); // this is the end. | |
| return; | |
| } | |
| selectNextItem.lastItemIndex = nextIndex; | |
| $(options[nextIndex]).click(); | |
| setTimeout(openPermissionLevelMenu, 1); | |
| } | |
| function openPermissionLevelMenu() { | |
| // normal jquery click() isn't good enough here, need to use https://stackoverflow.com/a/79096035/1067003 | |
| simulateMouseClick($("[data-testid=api_token_permissions_options]:last div:last")[0]); | |
| if (selectAccountOrZone.target === "Zone") { | |
| // for some reason, on Zone only, we have to double-click on every odd item.. WTF? | |
| if (selectNextItem.needDoubleClick) { | |
| delete selectNextItem.needDoubleClick; | |
| setTimeout(openPermissionLevelMenu, 1); | |
| } else { | |
| selectNextItem.needDoubleClick = true; | |
| setTimeout(clickOnHighestPermissionLevel, 1); | |
| } | |
| } else { | |
| setTimeout(clickOnHighestPermissionLevel, 1); | |
| } | |
| } | |
| function clickOnHighestPermissionLevel() { | |
| let options = $("div[id*=react-select-]"); | |
| if (selectAccountOrZone.target === "Zone") { | |
| $(options[options.length - 3]).click(); // -1 is the "Client IP Address Filtering" option, -2 is the "Zone Resources" option. | |
| } else { | |
| $(options[options.length - 2]).click(); // -1 is the "Client IP Address Filtering" option. | |
| } | |
| setTimeout(pressAddMore, 1); | |
| } | |
| setTimeout(pressAddMore, 1000); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment