Let's reverse-engineer Omegle. PROPERLY! ======================================== I didn't manage to find a proper, detailed (and up-to-date) reverse-engineerment of Omegle's text chat protocol on the interwebs, so here, have one! The responses are beautified and the query strings split up and URI-decoded for readability. E.g the real JSON queries don't have whitespaces between items. Note that "query string" refers to parameters encoded into the URL and "form data" to parameters in the request body which don't have to be URI-encoded. TODO: * Find out how college authorization works * Find out how WebRTC video streaming works * Generally phrase things better Used Request Headers: ``` Accept: application/json Accept-Encoding: gzip,deflate Accept-Language: en-US;q=0.6,en;q=0.4 Connection: keep-alive DNT: 1 Host: front9.omegle.com Origin: http://www.omegle.com Referer: http://www.omegle.com/ User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36 ``` Status ------ Pro-Tip: Fetch this first and then use one of the servers listed for future connections. You can just connect to the main server here. `GET http://[server].omegle.com/status` Query String: * `nocache = 0.4695589093025774` (optional, random nonce to prevent cached responses from being sent) * `randid = CHPZGFFW` (optional, see section "Start") Response: ``` { "count": 20840, (connection count, people say it's faked) "force_unmon": true, (see section "Getting b&") "antinudeservers": [ "waw3.omegle.com", "waw2.omegle.com", "waw1.omegle.com" ], "antinudepercent": 1.0, "spyQueueTime": 0.0, (if spyQueueTime is larger, there are more spies than spyees online, which the client uses to suggest a mode) "spyeeQueueTime": 2.173300027847, "timestamp": 1409233880.7561221, "servers": [ "front5.omegle.com", "front1.omegle.com", "front2.omegle.com", "front9.omegle.com", "front6.omegle.com", "front7.omegle.com", "front8.omegle.com", "front4.omegle.com", "front3.omegle.com" ] } ``` Start ----- This actually starts the chat and gets us our client ID. If you want to start a question/spy chat, send `wantsspy = 1` for spyee mode and `ask = blah` for spyer mode. `POST http://[server].omegle.com/start` Query String: * `rcs = 1` * `firstevents = 1` * `m = 1` (imitate a mobile connection, shouldn't really matter) * `lang = en` (two-char language code) * `randid = CHPZGFFW` (this is really just a random string containing 2-9 and A-Z) * `spid =` (some kind of ID from Adobe Stratus, never used though) * `topics = ["asdf", "test", ...]` (optional, for default mode) * `wantsspy = 1` (for spyee mode) * `ask = blah question?` (for spyer mode) * `cansavequestion = 1` (Omegle may reuse your question) * `group = unmon` (join the unmonitored section instead) Response: ``` { "events": [ ...see section "Events"... ], "clientID": "central2:k0m4akq5ry4ytvklsrs2jmtsjkpbkh" (needed for all subsequent requests) } ``` Events ------ This one uses long polling, which means that the server will be blocking the connection until an event happens. You can handle this with some async magic and long timeouts. `POST http://[server].omegle.com/events` Form Data: * `id = central2:k0m4akq5ry4ytvklsrs2jmtsjkpbkh` Response: ``` [ [...see below...], ... ] ``` ### Status events * `["waiting"]` (the server is searching for strangers) * `["connected"]` (you can start sending messages now) * `["statusInfo", {...stripped...}]` (see section "Status") ### Notifications * `["commonLikes", ["asdf", "test", ...]]` (the shared topics from the ones you've passed) * `["serverMessage", "blah"]` (most likely `You both speak the same language.`) * `["recaptchaRequired", "[challenge]"]` (see section "ReCAPTCHAs") * `["recaptchaRejected", "[challenge]"]` * `["identDigests", "blah,blah,blah"]` (probably just used for sharing logs) ### Error events (disconnects you) * `["error", "blah blah error text!"]` (general error message) * `["connectionDied"]` (some technical error) * `["antinudeBanned"]` (see section "Getting b8") ### Chat events * `["typing"]` (the stranger started typing) * `["stoppedTyping"]` (...stopped typing) * `["gotMessage", "blah"]` (...sent a message) * `["strangerDisconnected"]` (...decided to disconnect) ### In spyee mode * `["question", "blah?"]` (the question you'll discuss with the stranger) ### In spyer mode * `["question", "blah question?"]` (your question) * `["spyTyping", "Stranger <1/2>"]` (Stranger 1/2 started typing) * `["spyStoppedTyping", "Stranger <1/2>"]` (...stopped typing) * `["spyMessage", "Stranger <1/2>", "blah"]` (...sent a message) * `["spyDisconnected", "Stranger <1/2>"]` (...decided to disconnect) Send messages ------------- I'm not sure about the Unicode support, but it should work in most cases. `POST http://[server].omegle.com/send` Form Data: * `msg = lol` * `id = central2:k0m4akq5ry4ytvklsrs2jmtsjkpbkh` Response: ``` win ``` Set your "typing" status ------------------------ The server may detect clients that don't send these. `POST http://[server].omegle.com/typing` `POST http://[server].omegle.com/stoppedtyping` Form Data: * `id = central2:k0m4akq5ry4ytvklsrs2jmtsjkpbkh` Response: ``` win ``` Stop looking for common topics ------------------------------ If you've passed `topics` to `/start`, the server will send the `waiting` event and then search for people with the same topics until this gets posted. Use this to stop the running search, ignore the topics and continue with connecting. `POST http://[server].omegle.com/stoplookingforcommonlikes` Form Data: * `id = central2:k0m4akq5ry4ytvklsrs2jmtsjkpbkh` Response: ``` win ``` Disconnect from the current chat -------------------------------- Simple as that. Always use this to end sessions gracefully, unless noted beneath events. `POST http://[server].omegle.com/disconnect` Form Data: * `id = central2:k0m4akq5ry4ytvklsrs2jmtsjkpbkh` Response: ``` win ``` ReCAPTCHAS ---------- If you run into an `recaptchaRequired` event, you must prove that you're a human by fetching the captcha using the URL-encoded passed code from `http://www.google.com/recaptcha/api/image?c=[challenge]` and sending the answer like this. Note that I haven't tried this yet. `POST http://[server].omegle.com/recaptcha` Form Data: * `id = central2:k0m4akq5ry4ytvklsrs2jmtsjkpbkh` * `challenge = [challenge]` * `response = [answer]` Getting b& ---------- If you got an `antinudeBanned` event, chances are that the moderators banned you from the monitored section for "bad behaviour". This also applies if the server status object (see section "Status") has `force_unmon` set as `true`. You can retry by passing `group = unmon` to `/start`. That won't work if you got your IP banned because of too rapid connecting or advertising, though. Sharing logs ------------ To upload your logs to Omegles server, use this. Pro-Tip: You can actually pass any arbitrary text as the log (note the double brackets though). The first item is always the header, ("You're chatting with a random stranger on Omegle!") and the last the footer ("You have disconnected."). If the second item is "Question to discuss:", it will be styled with the third item to resemble the question box on the web client. Lines starting with "You:" and "Stranger:" will be coloured blue/red. `POST http://logs.omegle.com/generate` Form Data: * `logs = [["blah",...]]` (JSON table of the plaintext chat, split in lines) * `randid = CHPZGFFW` (Your random ID) * `topics = ["asdf", "test", ...]` (optional, the shared topics) * `identdigests = blah,blah,blah` (the most recent data from the `identDigests` event) * `host = 1` Response: 302 Found, the `Location` header contains the log link.