Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Omegle protocol reverse-engineering

Let's reverse-engineer Omegle. PROPERLY!

I could not find a proper, detailed (and up-to-date) reverse-engineerment of Omegle's text chat protocol on the internet, so here, have one made by analyzing the web app (web requests and source code).
The responses are beautified and the query strings split up and URI-decoded for readability.
Note that "query string" refers to parameters encoded into the URL and "form data" to parameters in the POST body which do not have to be URI-encoded.

TODO:

  • Find out how college authorization works
  • Find out how WebRTC video streaming works
  • Generally phrase things better

I hereby declare this document Public Domain. If you find it helpful for a project of yours, I only ask you to provide a link to it in your source so others interested can learn from it too.

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

Note that the headers X-Requested-With and X-Request are deliberately removed from requests by the JavaScript.

Status

Pro-Tip: Fetch this first and then use one of the servers/subs listed for future connections (you can just connect to the main server here). You should switch to another one if your current one is not listed anymore.

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, // your IP was banned, see "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 (answer a question) and ask = blah for spyer mode (ask a question).

POST http://[server].omegle.com/start

Query String

  • rcs = 1
  • firstevents = 1 (if 0 or not given, the response will not contain a statusInfo)
  • m = 1 (imitate a mobile connection, shouldn't really matter)
  • randid = CHPZGFFW (this is really just a random string containing 2-9 and A-Z, but excluding I and O)
  • spid = (some kind of ID from Adobe Stratus, never used though)
  • group = unmon (optional, join the unmonitored section instead)
  • lang = en (optional, two-char language code)
  • topics = ["foo", "bar", ...] (in default mode only)

Spyer/Spyee

  • wantsspy = 1 (for spyee mode)
  • ask = blah? (for spyer mode)
  • cansavequestion = 1 (optional, in spyer mode only, allow Omegle to reuse your question)

Camera Chat

  • webrtc = 1 (for camera chat)
  • camera = (probably just a flag, was " " for me in camera chat)

College Chat

  • college = ? (optional, TODO)
  • college_auth = ? (optional, TODO)
  • any_college = 1 (optional, TODO)

Response

{
    "events": [
        // see section "Events"
    ],
    "clientID": "central2:k0m4akq5ry4ytvklsrs2jmtsjkpbkh", // needed for all subsequent requests
    "statusInfo": {...} // see section "Status"
}

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 = [clientID]

Response

[
    // see below
    ["event", "argument 1", ...],
    ["event", "argument 1", "argument 2", ...],
    // ...
]

Status events

  • ["waiting"] (the server is searching for strangers)
  • ["connected"] (you can start sending messages now)
  • ["statusInfo", {...}] (see section "Status")
  • ["count", 20900] (update the connection/online count, never encountered this one but it's in the source)

Notifications

  • ["commonLikes", ["foo", "bar", ...]] (the shared topics from the ones you've passed)
  • ["partnerCollege", "Foobar College"] (chat partner goes to this college)
  • ["serverMessage", "blah"] (most likely You both speak the same language.)
  • ["recaptchaRequired", "ChALlEnGe"] (see section "ReCAPTCHAs")
  • ["recaptchaRejected", "ChALlEnGe"]
  • ["identDigests", "a,b,c"] (probably only used for sharing logs)

Error events (disconnects you)

  • ["error", "blah!"] (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?"] (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)

In camera chat

  • ["icecandidate", "blah"] (see section "Connecting to the WebRTC peer")
  • ["rtccall", "blah"] (TODO)
  • ["rtcpeerdescription"] (see section "Send WebRTC Peer description")

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 = [clientID]

Response

win

Set your "typing" status

The server might detect clients that do not send these.

POST http://[server].omegle.com/typing
POST http://[server].omegle.com/stoppedtyping

Form Data

  • id = [clientID]

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 the client sends this. Use it after some time to stop the running search, ignore the topics and continue with connecting.

POST http://[server].omegle.com/stoplookingforcommonlikes

Form Data

  • id = [clientID]

Response

win

Disconnect from the current chat

Simple as that. Always use this to end sessions gracefully, unless another event already ended the session. This can also be used to disconnect both strangers in the spyer mode.

POST http://[server].omegle.com/disconnect

Form Data

  • id = [clientID]

Response

win

Send WebRTC Peer description

TODO

Send WebRTC ICE candidates

This is what you should do when your RTCPeerConnection fires the onicecandidate event. Basically, the Omegle client stores all received candidates in a list and then sets a 300ms timeout for more candidates to get pushed onto the list after which it sends the list to the server and clears it.

POST http://[server].omegle.com/icecandidate

Form Data

  • id = [clientID]
  • candidate = %7B...%7D (url-encoded JSON representation of a candidate)
  • candidate = ... (multiple times)

Response

win

Connecting to the WebRTC peer

TODO

ReCAPTCHAS

If you run into an recaptchaRequired event, you must prove that you are 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 = [clientID]
  • challenge = [challenge]
  • response = [answer]

Getting b&

If you got an antinudeBanned event, the modarating system banned you from the monitored section for "bad behaviour". From now on, the server status object (see section "Status") will have force_unmon set to true. You can switch to the unmonitored section by passing group = unmon to /start. They won't give you this mercy if you got your IP banned by connecting too rapidly or advertising, but bans don't last forever anyway.

Sharing logs

To upload your logs to Omegles server, use this.
Pro-Tip: You can actually pass any arbitrary text as the log. It's a JSON-encoded list containing lists that contain the strings. Oh, and HTML injection doesn't work, I tried.

These are the triggers that add some formatting:

  • ["*"] (smaller, bold font, gray)
  • ["* disconnected"] (as above)
  • ["Question to discuss:", "*"] (blue question box)
  • ["Stranger:", "*"] (large font, first item is red)
  • ["Stranger 1:", "*"] (as above)
  • ["Stranger 2:", "*"] (large font, first item is blue)
  • ["You:", "*"] (as above)
  • ["*", "*"] (normal font, first item is bold)

POST http://logs.omegle.com/generate

Form Data

  • log = [["You:", "blah"], ...] (JSON table of the plaintext chat, split in lines)
  • randid = CHPZGFFW (Your random ID)
  • topics = ["foo", "bar", ...] (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 in the format http://logs.omegle.com/[id]. The log image can be fetched from http://l.omegle.com/[id].png.

@mynameisfashanu

This comment has been minimized.

Copy link

commented Dec 26, 2014

good guide!

@Murchurl

This comment has been minimized.

Copy link

commented Jan 15, 2015

I'm not entirely sure how this works, POST http://[server].omegle.com/disconnect?id=central2:k0m4akq5ry4ytvklsrs2jmtsjkpbkh

Is the client ID encrypted or something, because everytime I call this I get fail. Same goes for events except it returns null.

@nucular

This comment has been minimized.

Copy link
Owner Author

commented Feb 27, 2015

Are you using the client ID you got from http://[server].omegle.com/start?
Also, sorry for the late reply, I didn't get any notification about your comment.

@tmerr

This comment has been minimized.

Copy link

commented Nov 4, 2015

I think the first field in the form data for http://logs.omegle.com/generate should be log, not logs

@GiedriusS

This comment has been minimized.

Copy link

commented Dec 20, 2015

/start may not have firstevents necessarily set to 1. If it's 0 or non-existant then statusInfo will not exist and you will have to call /status explicitly. Also, missing section about college mode.

@freehuntx

This comment has been minimized.

Copy link

commented Dec 22, 2015

the spid at start is the next rtmfp rendevouz server id i think.
Its needed for rtmfp p2p communication (video).

You get it, if you connect to the p2p rtmfp server (rtmfp://p2p.rtmfp.net) and provide a proper omegle password. (6fd539b64a3ca859d410f2f6-ac89c5a8742e)

@alexbinary

This comment has been minimized.

Copy link

commented Oct 6, 2017

The server list in Status does not include .omegle.com :

  "servers":  ["front6", "front1", "front13", "front8", "front9", "front15"]
@algiuxass

This comment has been minimized.

Copy link

commented Dec 19, 2018

"recaptchaRequired", "recaptchaRejected" events are no longer working. Omegle now uses reCAPTCHA v2 (or v3, not quite sure). That means if you need to enter captcha(which you need to do every hour or two hours, not sure about this too), an event "error" will be sent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.