Skip to content

Instantly share code, notes, and snippets.

@hitthemoney
Last active May 1, 2024 08:03
Show Gist options
  • Save hitthemoney/a5b7707417c2ba2b2f3303f35135bf3e to your computer and use it in GitHub Desktop.
Save hitthemoney/a5b7707417c2ba2b2f3303f35135bf3e to your computer and use it in GitHub Desktop.
This markdown file explains Krunker.io's social websockets and how to connect, get data from them, captchas, and more.

Krunker WebSockets Explained

WebSocket

WebSocket is a protocol over http. You should read: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API for more info on WebSocket.

Encoding/Decoding

Krunker uses msgpack for decoding and encoding packets. Msgpack is also smaller and sometimes faster depending on the implementation you use/make.

Packets

Like I said earlier, Krunker uses msgpack for decoding and encoding packets. A ping packet would like this: ["po"] which you send when you get a ["pi"] packet, and the ping result packet you receive is ["pir", <ping-result: int>]. For fetching a profile, you can use ["r", "profile", <username: string>, null]. The result packet would be like ["0", "profile", <username: string>, <profile-data: object>, <map-data: object>, <mod-data: object>, ...etc]. For finding packets, you can download https://krunker.io/social.html using a command like cURL, formatting the file and looking at the JavaScript, looking at your websocket viewer in dev tools under network (which will not work that well because your browser does not know the encoding of the packet), or using a WebSocket data viewer script like: https://github.com/Lemons1337/WebSocket-Data-Viewer/blob/master/script.user.js, and monitoring outgoing/incoming packets on krunker social.

Making the request

Like I said before, krunker uses WebSocket. Their social WebSocket url is wss://social.krunker.io/ws. Also, Krunker does an origin check, so that other sites cannot connect to their severs. To get past this, add this header to your websocket handshake headers (wont work in browser for security reasons), Origin: https://krunker.io. If you get an ["error", "Y8S Error"] packet, or something similar to that, you would know that the origin header did not work.

Captcha

Krunker Social uses hCaptcha for accessing their websockets (sometimes), and reCaptcha v3 for some packets like, logging in, fetching the market, and inventories. ReCaptcha v2 is very very hard to solve without something like puppeteer or maybe selenium. To detect if a packet needs recaptcha, normally the last part in it should have a huge string full of random characters. If you get a ["cpt"] it means you must solve an hCaptcha and send the captcha result back with the ["cptR", <captcha-result: string>] + two null bytes (\0) packet. To solve hCaptchas I (hitthemoney) forked an hcaptcha solving library for nodejs, and fixed/improved it. You can find this here: https://github.com/hitthemoney/hcaptcha-solver. HCaptcha sadly patched a bug which made it so if you gave them an invalid site key, all difficulty and other site settings would be lifted, allowing you to give random inputs and get a good result. Now random often would not do it (currently does not work so well), so someone can modify my forked hcaptcha-solver source and maybe add image recognition for faster solves. Also Krunker's hCaptcha site key is 60a46f6a-e214-4aa8-b4df-4386e68dfde4 and their reCaptcha site key is 6LdvBrQUAAAAAL6gtEpVNzii_3nQkbOyx912nvlm.

Examples

Ping/Pong Example with NodeJS (JavaScript)

This example uses the ws package, msgpack-lite package, and @hitthemoney/hcaptcha-solver package all on npm.

// include dependencies
const WebSocket = require("ws");
const msgpack = require("msgpack-lite");
const solveCaptcha = require("@hitthemoney/hcaptcha-solver");
// Krunker's hcaptcha site key
const cptSiteKey = "60a46f6a-e214-4aa8-b4df-4386e68dfde4";

// create the websocket connection
const sock = new WebSocket("wss://social.krunker.io/ws", {
    headers: {
        origin: "https://krunker.io" // add origin header
    }
});

const sendData = (data) => {
    console.log("Outgoing ->", data);

    sock.send(msgpack.encode(data).buffer); // encode the data with msgpack.encode and send it
}

// set binary type to arraybuffer
sock.binaryType = "arraybuffer";

// on socket open, log "connected" to stdout
sock.onopen = () => {
    console.log("connected");
}

// when the socket gets a message...
sock.onmessage = (event) => {
    let data = msgpack.decode(new Uint8Array(event.data)); // decode the binary data with msgpack.decode

    console.log("Incoming ->", data);

    // make cases for packet code
    switch (data[0]) {
        // when it gets a ping
        case "pi":
            sendData(["po"]);
            break;
        // if it gets a captcha packet, solve it and send it
        case "cpt": 
            solveCaptcha("https://krunker.io", { siteKey: cptSiteKey, maxRetries: 10, retryDelay: 100 })
                // on success
                .then(token => {
                    sendData(["cptR", token, 0, 0]);
                })
                // on fail
                .catch(err => {
                    console.error("Failed to solve captcha.", err.message);
                    // exit with an error code (1)
                    return process.exit(1);
                })
            break;
    }
}
@North-West-Wind
Copy link

The Captcha solving part doesn't work

@hitthemoney
Copy link
Author

hitthemoney commented Jul 27, 2021

yeah you will have to find another way for the captcha now I believe
I can try fix the solver but not right now

@AssisrMatheus
Copy link

I'm planning on making a (simpler) networked game with three.js like krunker. Do you know if they use any library to handle netcode? Is it custom?

Do you know if they use socket.io or native socket API? Any resources on that? Thank you!

@hitthemoney
Copy link
Author

They use the WebSocket library and msgpack to decode/encode packets.
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
https://msgpack.org/index.html

@Theraqa
Copy link

Theraqa commented Mar 23, 2022

Hey does krunker still use msgpack? becasue im trying to encode Login Payload and server always responds me with ��error�Socket error�000006
this is my code to encode

var msgpack = require("msgpack-lite");

var payload = ["a",1,[USERNAME,PASSWORD,null]]

var msg = msgpack.encode(payload).toString("base64")

No matter what i try it always encodes differently and never works... can you help me out?

@hitthemoney
Copy link
Author

Hey does krunker still use msgpack? becasue im trying to encode Login Payload and server always responds me with ��error�Socket error�000006 this is my code to encode

var msgpack = require("msgpack-lite");

var payload = ["a",1,[USERNAME,PASSWORD,null]]

var msg = msgpack.encode(payload).toString("base64")

No matter what i try it always encodes differently and never works... can you help me out?

You don't want to use .toString("base64"), you want to get the buffer from it by using, .buffer

@callmedandann
Copy link

@hitthemoney bro can I have your discord?

@hitthemoney
Copy link
Author

@callmedandann My discord is hitthemoney#1337

@CodeDiseaseDev
Copy link

sometimes when i send the 'po' packet
i get disconnected with the error ["error","INVALID VERSION"]

im making a client with dropout btw
i believe you've spoken to him already?

@hitthemoney
Copy link
Author

sometimes when i send the 'po' packet i get disconnected with the error ["error","INVALID VERSION"]

im making a client with dropout btw i believe you've spoken to him already?

you sure your just making a client 🤨

@kgurchiek
Copy link

Hello, I know this is a bit old, but I tried this ping/pong example, and I get [ 'error', 'Socket error', '000006' ] as soon as the pong response is sent. Is something outdated? (This happens as soon as I try to send anything over the ws, no matter what it is)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment