Here is a prebuilt lib for it:
/**
* Fallback manual authorization token.
* Populate this only if the Vencord Webpack cache is unavailable.
* @type {string}
*/
const MANUAL_TOKEN = "";
/**
* Base endpoint URL for the Discord Gorilla activity.
* @type {string}
*/
const BASE_URL = "https://discord.com/api/v9/gorilla/activity";
/**
* Safely extracts the Discord authorization token.
* Prioritizes Vencord's internal Webpack cache, falling back to MANUAL_TOKEN if necessary.
*
* @returns {string|null} The authorization token, or null if unavailable.
*/
const getToken = () => {
const vencordToken = window.Vencord?.Webpack?.findByProps("getToken")?.getToken();
return MANUAL_TOKEN || vencordToken;
};
/**
* Generates a dynamic telemetry payload for the x-super-properties header.
* Utilizes the current browser environment to construct an authentic client profile.
*
* @returns {string} Base64 encoded JSON string representing client properties.
*/
const getDynamicSuperProperties = () => {
const buildNumber = window.GLOBAL_ENV?.BUILD_NUMBER ?? 522736;
const userAgent = navigator.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36";
const browserVersionMatch = userAgent.match(/Chrome\/(\d+\.\d+\.\d+\.\d+)/);
const browserVersion = browserVersionMatch?.[1] || "144.0.0.0";
const properties = {
os: "Windows",
browser: "Chrome",
device: "",
system_locale: "en-US",
has_client_mods: false,
browser_user_agent: userAgent,
browser_version: browserVersion,
os_version: "10",
referrer: "",
referring_domain: "",
referrer_current: "",
referring_domain_current: "",
release_channel: "stable",
client_build_number: buildNumber,
client_event_source: null,
client_launch_id: null,
launch_signature: null,
client_heartbeat_session_id: null,
client_app_state: "focused"
};
return btoa(JSON.stringify(properties));
};
/**
* Executes an authenticated POST request to the specified activity endpoint.
*
* @param {string} endpoint - The specific API endpoint route.
* @returns {Promise<Object>} The JSON response payload.
* @throws {Error} Throws an error if no authorization token is located.
*/
const sendGorillaAction = async (endpoint) => {
const token = getToken();
if (!token) {
throw new Error("[Auth] No Discord token found. Please populate MANUAL_TOKEN.");
}
const response = await fetch(`${BASE_URL}/${endpoint}`, {
method: "POST",
headers: {
"accept": "*/*",
"accept-language": "en-US",
"authorization": token,
"priority": "u=1, i",
"sec-ch-ua": "\"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"144\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-super-properties": getDynamicSuperProperties()
},
referrer: "https://discord.com/channels/@me",
body: null,
mode: "cors",
credentials: "include"
});
if (!response.ok) {
console.error(`[Error] Request to ${endpoint} failed with status ${response.status}`);
}
return response.json();
};
/**
* Initiates and completes a crafting lifecycle.
* Exposed to the global window object for console execution.
*
* @async
* @global
* @returns {Promise<Object|undefined>} The state changes resulting from the action.
*/
window.craft = async () => {
console.log("π¨ [Craft] Starting...");
await sendGorillaAction("crafting/start");
console.log("π¨ [Craft] Completing...");
const result = await sendGorillaAction("crafting/complete");
return result?.changes;
};
/**
* Initiates and completes a combat lifecycle.
* Exposed to the global window object for console execution.
*
* @async
* @global
* @returns {Promise<Object|undefined>} The state changes resulting from the action.
*/
window.battle = async () => {
console.log("βοΈ [Battle] Starting...");
await sendGorillaAction("combat/start");
console.log("βοΈ [Battle] Completing...");
const result = await sendGorillaAction("combat/complete");
return result?.changes;
};
/**
* Completes a pending adventure gathering lifecycle and initiates a new one.
* Exposed to the global window object for console execution.
*
* @async
* @global
* @returns {Promise<Object|undefined>} The state changes resulting from the action.
*/
window.adventure = async () => {
console.log("π [Adventure] Starting adventure...");
await sendGorillaAction("gathering/start");
console.log("π [Adventure] Completing adventure...");
const result = await sendGorillaAction("gathering/complete");
return result?.changes;
};
console.log("%cβ
Gorilla Automation Loaded!", "color: #43b581; font-weight: bold; font-size: 14px;");
console.log("Commands: await battle(), await craft(), await adventure()");Yeah, it's AI-Generated because I don't like typing. But I'll walk you through it.
The JWT token is basically this:
{
"os": "Windows",
"browser": "Chrome",
"device": "",
"system_locale": "en-US",
"has_client_mods": false,
"browser_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36",
"browser_version": "144.0.0.0",
"os_version": "10",
"referrer": "",
"referring_domain": "",
"referrer_current": "wherever u are rn",
"referring_domain_current": "discord.com",
"release_channel": "stable",
"client_build_number": 522736,
"client_event_source": null,
"client_launch_id": "XXXX",
"launch_signature": "XXXX",
"client_heartbeat_session_id": "XXXX",
"client_app_state": "focused"
}I basically stripped everything that wasn't necessary (the server didn't care about). I reconstruct the JWT with minimal stuff needed for auth as seen above.
I removed a lot of other headers that didn't seem to be required.
Will this raise flags? Probably. Will this work? Yes.
Will you need to modify this to not look like a bot? Absolutely. You may include more headers and more JWT fields if you have Vencord and can directly access the required properties.
Made this in an hour but happy to help / learn.
make sure discord doesnt listen to mouseclick / mousemove events when u do this asw bcs apparently that gets flagged too?