Created
August 30, 2025 17:48
-
-
Save SpaceSaver/2be3bb2359040c7ac5fe9c6538864d42 to your computer and use it in GitHub Desktop.
ChatGPT Model Selector
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 ChatGPT Model Override | |
// @namespace SpaceSaver Scripts | |
// @match https://chatgpt.com/* | |
// @grant none | |
// @version 2.0 | |
// @author SpaceSaver UnderCover (/u/SpaceSaver2000-1) | |
// @description Adds a more advanced model selector to ChatGPT enabling you to save your GPT-4o credits for when you need them! | |
// @run-at document-start | |
// ==/UserScript== | |
(() => { | |
const HEADER_QUERY_STRING = "nav > .bottom-0"; | |
let models = null; | |
const originalFetch = window.fetch; | |
async function fetchInterceptor(...args) { | |
if (!window.localStorage.getItem("selected-model")) { | |
window.localStorage.setItem("selected-model", "gpt-4o-mini"); | |
} | |
//args[0] = new String(args[0][0]) | |
if (typeof(args[0]) != "string") return originalFetch(...args); | |
console.log(args[0]); | |
if (args[0].endsWith("/backend-api/conversation") || args[0].endsWith("/backend-api/f/conversation") && args[1]?.body) { | |
const bodyJSON = JSON.parse(args[1].body); | |
bodyJSON.model = window.localStorage.getItem("selected-model"); | |
args[1].body = JSON.stringify(bodyJSON); | |
/*} else if (args[0].split("?")[0].endsWith("/backend-api/models")) { | |
const res = await originalFetch(...args); | |
const textRes = await res.text(); | |
res.text = async () => {return textRes}; | |
res.json = async () => {return JSON.parse(textRes)}; | |
models = JSON.parse(textRes).models; | |
setTimeout(() => loadMenu(), 30000); | |
return res; | |
*/ | |
} else if (args[0].endsWith("/backend-api/conversation/init") && args[1]?.body) { | |
return | |
//If we do this it doesn't acknowledge that certain chats are disabled since 4o ratelimit has been reached 💀 | |
/* | |
const res = await originalFetch(...args); | |
let textRes = await res.text(); | |
textRes = JSON.parse(textRes); | |
if (textRes.blocked_features && textRes.blocked_features.filter(elem => {return elem.name == "send"}).length > 0) { | |
const newBlocked = []; | |
for (let x = 0; x < textRes.blocked_features.length; x++) { | |
if (textRes.blocked_features[x].name != "send") { | |
newBlocked.push(textRes.blocked_features[x]); | |
} | |
} | |
textRes.blocked_features = newBlocked; | |
} | |
console.log(textRes); | |
textRes = JSON.stringify(textRes); | |
res.text = async () => {return textRes}; | |
res.json = async () => {return JSON.parse(textRes)}; | |
*/ | |
} | |
return await originalFetch(...args); | |
} | |
window.fetch = fetchInterceptor; | |
window.addEventListener("load",() => setTimeout( async () => { | |
console.log("Getting sh*t myself") | |
const headers = {}; | |
try { | |
headers.Authorization = "Bearer " + document.documentElement.innerHTML.split('\\"accessToken\\",\\"')[1].split('\\"')[0]//window.__reactRouterContext.state.loaderData.root.clientBootstrap.session.accessToken; | |
} catch(e) { | |
console.log("Couldn't find token, probably logged out lol.") | |
} | |
models = (await ( await fetch("https://chatgpt.com/backend-api/models", {headers, credentials: "include"})).json()).models; | |
loadMenu(); | |
}, 5000)); | |
const loadMenu = () => { | |
const header = document.querySelector(HEADER_QUERY_STRING); | |
const selector = document.createElement("select"); | |
for (const model of models) { | |
const opt = document.createElement("option"); | |
opt.textContent = model.title; | |
opt.value = model.slug; | |
selector.appendChild(opt); | |
} | |
selector.style.backgroundColor = "var(--sidebar-surface-primary)"; | |
selector.style.borderRadius = "15px"; | |
selector.value = window.localStorage.getItem("selected-model"); | |
selector.addEventListener("change", e => { | |
window.localStorage.setItem("selected-model", e.target.value); | |
}); | |
header.insertBefore(selector, header.children[header.children.length - 1]); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment