{"id":14978170,"url":"https://github.com/socketio/socket.io-protocol","last_synced_at":"2025-04-04T20:15:12.722Z","repository":{"id":5867682,"uuid":"7084905","full_name":"socketio/socket.io-protocol","owner":"socketio","description":"Socket.IO Protocol specification","archived":false,"fork":false,"pushed_at":"2023-12-28T22:21:45.000Z","size":88,"stargazers_count":510,"open_issues_count":3,"forks_count":62,"subscribers_count":100,"default_branch":"main","last_synced_at":"2025-03-28T19:11:18.017Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://socket.io","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/socketio.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2012-12-09T23:24:47.000Z","updated_at":"2025-01-08T23:35:37.000Z","dependencies_parsed_at":"2023-01-11T17:01:43.566Z","dependency_job_id":"10c57070-98c7-4a86-add6-0ea011c461a5","html_url":"https://github.com/socketio/socket.io-protocol","commit_stats":{"total_commits":47,"total_committers":7,"mean_commits":6.714285714285714,"dds":0.574468085106383,"last_synced_commit":"4f633dd6a4445492d57af3b27ddd2d336014f1f1"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socketio%2Fsocket.io-protocol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socketio%2Fsocket.io-protocol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socketio%2Fsocket.io-protocol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socketio%2Fsocket.io-protocol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/socketio","download_url":"https://codeload.github.com/socketio/socket.io-protocol/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247242681,"owners_count":20907134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-24T13:56:58.822Z","updated_at":"2025-04-04T20:15:12.700Z","avatar_url":"https://github.com/socketio.png","language":"JavaScript","readme":"# Socket.IO Protocol\n\nThis document describes the 5th version of the Socket.IO protocol.\n\n**Table of content**\n\n- [Introduction](#introduction)\n- [Exchange protocol](#exchange-protocol)\n  - [Connection to a namespace](#connection-to-a-namespace)\n  - [Sending and receiving data](#sending-and-receiving-data)\n  - [Acknowledgement](#acknowledgement)\n  - [Disconnection from a namespace](#disconnection-from-a-namespace)\n- [Packet encoding](#packet-encoding)\n  - [Format](#format)\n  - [Examples](#examples)\n    - [Connection to a namespace](#connection-to-a-namespace-1)\n    - [Sending and receiving data](#sending-and-receiving-data-1)\n    - [Acknowledgement](#acknowledgement-1)\n    - [Disconnection from a namespace](#disconnection-from-a-namespace-1)\n- [Sample session](#sample-session)\n- [History](#history)\n  - [Difference between v5 and v4](#difference-between-v5-and-v4)\n  - [Difference between v4 and v3](#difference-between-v4-and-v3)\n  - [Difference between v3 and v2](#difference-between-v3-and-v2)\n  - [Difference between v2 and v1](#difference-between-v2-and-v1)\n  - [Initial revision](#initial-revision)\n- [Test suite](#test-suite)\n\n\n## Introduction\n\nThe Socket.IO protocol enables [full-duplex](https://en.wikipedia.org/wiki/Duplex_(telecommunications)#FULL-DUPLEX) and low-overhead communication between a client and a server.\n\nIt is built on top of [the Engine.IO protocol](https://github.com/socketio/engine.io-protocol), which handles the low-level plumbing with WebSocket and HTTP long-polling.\n\nThe Socket.IO protocol adds the following features:\n\n- multiplexing (referred as [\"namespace\"](https://socket.io/docs/v4/namespaces) in the Socket.IO jargon)\n\nExample with the JavaScript API:\n\n*Server*\n\n```js\n// declare the namespace\nconst namespace = io.of(\"/admin\");\n// handle the connection to the namespace\nnamespace.on(\"connection\", (socket) =\u003e {\n  // ...\n});\n```\n\n*Client*\n\n```js\n// reach the main namespace\nconst socket1 = io();\n// reach the \"/admin\" namespace (with the same underlying WebSocket connection)\nconst socket2 = io(\"/admin\");\n// handle the connection to the namespace\nsocket2.on(\"connect\", () =\u003e {\n  // ...\n});\n```\n\n- acknowledgement of packets\n\nExample with the JavaScript API:\n\n```js\n// on one side\nsocket.emit(\"hello\", \"foo\", (arg) =\u003e {\n  console.log(\"received\", arg);\n});\n\n// on the other side\nsocket.on(\"hello\", (arg, ack) =\u003e {\n  ack(\"bar\");\n});\n```\n\nThe reference implementation is written in [TypeScript](https://www.typescriptlang.org/):\n\n- server: https://github.com/socketio/socket.io\n- client: https://github.com/socketio/socket.io-client\n\n\n## Exchange protocol\n\nA Socket.IO packet contains the following fields:\n\n- a packet type (integer)\n- a namespace (string)\n- optionally, a payload (Object | Array)\n- optionally, an acknowledgment id (integer)\n\nHere is the list of available packet types:\n\n| Type          | ID  | Usage                                                                                 |\n|---------------|-----|---------------------------------------------------------------------------------------|\n| CONNECT       | 0   | Used during the [connection to a namespace](#connection-to-a-namespace).              |\n| DISCONNECT    | 1   | Used when [disconnecting from a namespace](#disconnection-from-a-namespace).          |\n| EVENT         | 2   | Used to [send data](#sending-and-receiving-data) to the other side.                   |\n| ACK           | 3   | Used to [acknowledge](#acknowledgement) an event.                                     |\n| CONNECT_ERROR | 4   | Used during the [connection to a namespace](#connection-to-a-namespace).              |\n| BINARY_EVENT  | 5   | Used to [send binary data](#sending-and-receiving-data) to the other side.            |\n| BINARY_ACK    | 6   | Used to [acknowledge](#acknowledgement) an event (the response includes binary data). |\n\n\n### Connection to a namespace\n\nAt the beginning of a Socket.IO session, the client MUST send a `CONNECT` packet:\n\nThe server MUST respond with either:\n\n- a `CONNECT` packet if the connection is successful, with the session ID in the payload\n- or a `CONNECT_ERROR` packet if the connection is not allowed\n\n```\nCLIENT                                                      SERVER\n\n  │  ───────────────────────────────────────────────────────►  │\n  │             { type: CONNECT, namespace: \"/\" }              │\n  │  ◄───────────────────────────────────────────────────────  │\n  │   { type: CONNECT, namespace: \"/\", data: { sid: \"...\" } }  │\n```\n\nIf the server does not receive a `CONNECT` packet first, then it MUST close the connection immediately.\n\nA client MAY be connected to multiple namespaces at the same time, with the same underlying WebSocket connection.\n\nExamples:\n\n- with the main namespace (named `\"/\"`)\n\n```\nClient \u003e { type: CONNECT, namespace: \"/\" }\nServer \u003e { type: CONNECT, namespace: \"/\", data: { sid: \"wZX3oN0bSVIhsaknAAAI\" } }\n```\n\n- with a custom namespace\n\n```\nClient \u003e { type: CONNECT, namespace: \"/admin\" }\nServer \u003e { type: CONNECT, namespace: \"/admin\", data: { sid: \"oSO0OpakMV_3jnilAAAA\" } }\n```\n\n- with an additional payload\n\n```\nClient \u003e { type: CONNECT, namespace: \"/admin\", data: { \"token\": \"123\" } }\nServer \u003e { type: CONNECT, namespace: \"/admin\", data: { sid: \"iLnRaVGHY4B75TeVAAAB\" } }\n```\n\n- in case the connection is refused\n\n```\nClient \u003e { type: CONNECT, namespace: \"/\" }\nServer \u003e { type: CONNECT_ERROR, namespace: \"/\", data: { message: \"Not authorized\" } }\n```\n\n### Sending and receiving data\n\nOnce the [connection to a namespace](#connection-to-a-namespace) is established, the client and the server can begin exchanging data:\n\n```\nCLIENT                                                      SERVER\n\n  │  ───────────────────────────────────────────────────────►  │\n  │        { type: EVENT, namespace: \"/\", data: [\"foo\"] }      │\n  │                                                            │\n  │  ◄───────────────────────────────────────────────────────  │\n  │        { type: EVENT, namespace: \"/\", data: [\"bar\"] }      │\n```\n\nThe payload is mandatory and MUST be a non-empty array. If that's not the case, then the receiver MUST close the connection.\n\nExamples:\n\n- with the main namespace\n\n```\nClient \u003e { type: EVENT, namespace: \"/\", data: [\"foo\"] }\n```\n\n- with a custom namespace\n\n```\nServer \u003e { type: EVENT, namespace: \"/admin\", data: [\"bar\"] }\n```\n\n- with binary data\n\n```\nClient \u003e { type: BINARY_EVENT, namespace: \"/\", data: [\"baz\", \u003cBuffer \u003c01 02 03 04\u003e\u003e ] }\n```\n\n### Acknowledgement\n\nThe sender MAY include an event ID in order to request an acknowledgement from the receiver:\n\n```\nCLIENT                                                      SERVER\n\n  │  ───────────────────────────────────────────────────────►  │\n  │   { type: EVENT, namespace: \"/\", data: [\"foo\"], id: 12 }   │\n  │  ◄───────────────────────────────────────────────────────  │\n  │    { type: ACK, namespace: \"/\", data: [\"bar\"], id: 12 }    │\n```\n\nThe receiver MUST respond with an `ACK` packet with the same event ID.\n\nThe payload is mandatory and MUST be an array (possibly empty).\n\nExamples:\n\n- with the main namespace\n\n```\nClient \u003e { type: EVENT, namespace: \"/\", data: [\"foo\"], id: 12 }\nServer \u003e { type: ACK, namespace: \"/\", data: [], id: 12 }\n```\n\n- with a custom namespace\n\n```\nServer \u003e { type: EVENT, namespace: \"/admin\", data: [\"foo\"], id: 13 }\nClient \u003e { type: ACK, namespace: \"/admin\", data: [\"bar\"], id: 13 }\n```\n\n- with binary data\n\n```\nClient \u003e { type: BINARY_EVENT, namespace: \"/\", data: [\"foo\", \u003cbuffer \u003c01 02 03 04\u003e ], id: 14 }\nServer \u003e { type: ACK, namespace: \"/\", data: [\"bar\"], id: 14 }\n\nor\n\nServer \u003e { type: EVENT, namespace: \"/\", data: [\"foo\" ], id: 15 }\nClient \u003e { type: BINARY_ACK, namespace: \"/\", data: [\"bar\", \u003cbuffer \u003c01 02 03 04\u003e], id: 15 }\n```\n\n### Disconnection from a namespace\n\nAt any time, one side can end the connection to a namespace by sending a `DISCONNECT` packet:\n\n```\nCLIENT                                                      SERVER\n\n  │  ───────────────────────────────────────────────────────►  │\n  │           { type: DISCONNECT, namespace: \"/\" }             │\n```\n\nNo response is expected from the other side. The low-level connection MAY be kept alive if the client is connected to another namespace.\n\n\n## Packet encoding\n\nThis section details the encoding used by the default parser which is included in Socket.IO server and client, and\nwhose source can be found [here](https://github.com/socketio/socket.io-parser).\n\nThe JavaScript server and client implementations also supports custom parsers, which have different tradeoffs and may benefit to\ncertain kind of applications. Please see [socket.io-json-parser](https://github.com/socketio/socket.io-json-parser)\nor [socket.io-msgpack-parser](https://github.com/socketio/socket.io-msgpack-parser) for example.\n\nPlease also note that each Socket.IO packet is sent as a Engine.IO `message` packet (more information [here](https://github.com/socketio/engine.io-protocol)),\nso the encoded result will be prefixed by the character `\"4\"` when sent over the wire (in the request/response body with HTTP\nlong-polling, or in the WebSocket frame).\n\n### Format\n\n```\n\u003cpacket type\u003e[\u003c# of binary attachments\u003e-][\u003cnamespace\u003e,][\u003cacknowledgment id\u003e][JSON-stringified payload without binary]\n\n+ binary attachments extracted\n```\n\nNote: the namespace is only included if it is different from the main namespace (`/`)\n\n### Examples\n\n#### Connection to a namespace\n\n- with the main namespace\n\n*Packet*\n\n```\n{ type: CONNECT, namespace: \"/\" }\n```\n\n*Encoded*\n\n```\n0\n```\n\n- with a custom namespace\n\n*Packet*\n\n```\n{ type: CONNECT, namespace: \"/admin\", data: { sid: \"oSO0OpakMV_3jnilAAAA\" } }\n```\n\n*Encoded*\n\n```\n0/admin,{\"sid\":\"oSO0OpakMV_3jnilAAAA\"}\n```\n\n- in case the connection is refused\n\n*Packet*\n\n```\n{ type: CONNECT_ERROR, namespace: \"/\", data: { message: \"Not authorized\" } }\n```\n\n*Encoded*\n\n```\n4{\"message\":\"Not authorized\"}\n```\n\n#### Sending and receiving data\n\n- with the main namespace\n\n*Packet*\n\n```\n{ type: EVENT, namespace: \"/\", data: [\"foo\"] }\n```\n\n*Encoded*\n\n```\n2[\"foo\"]\n```\n\n- with a custom namespace\n\n*Packet*\n\n```\n{ type: EVENT, namespace: \"/admin\", data: [\"bar\"] }\n```\n\n*Encoded*\n\n```\n2/admin,[\"bar\"]\n```\n\n- with binary data\n\n*Packet*\n\n```\n{ type: BINARY_EVENT, namespace: \"/\", data: [\"baz\", \u003cBuffer \u003c01 02 03 04\u003e\u003e ] }\n```\n\n*Encoded*\n\n```\n51-[\"baz\",{\"_placeholder\":true,\"num\":0}]\n\n+ \u003cBuffer \u003c01 02 03 04\u003e\u003e\n```\n\n- with multiple attachments\n\n*Packet*\n\n```\n{ type: BINARY_EVENT, namespace: \"/admin\", data: [\"baz\", \u003cBuffer \u003c01 02\u003e\u003e, \u003cBuffer \u003c03 04\u003e\u003e ] }\n```\n\n*Encoded*\n\n```\n52-/admin,[\"baz\",{\"_placeholder\":true,\"num\":0},{\"_placeholder\":true,\"num\":1}]\n\n+ \u003cBuffer \u003c01 02\u003e\u003e\n+ \u003cBuffer \u003c03 04\u003e\u003e\n```\n\nPlease remember that each Socket.IO packet is wrapped in a Engine.IO `message` packet, so they will be prefixed by the character `\"4\"` when sent over the wire.\n\nExample: `{ type: EVENT, namespace: \"/\", data: [\"foo\"] }` will be sent as `42[\"foo\"]`\n\n#### Acknowledgement\n\n- with the main namespace\n\n*Packet*\n\n```\n{ type: EVENT, namespace: \"/\", data: [\"foo\"], id: 12 }\n```\n\n*Encoded*\n\n```\n212[\"foo\"]\n```\n\n- with a custom namespace\n\n*Packet*\n\n```\n{ type: ACK, namespace: \"/admin\", data: [\"bar\"], id: 13 }\n```\n\n*Encoded*\n\n```\n3/admin,13[\"bar\"]`\n```\n\n- with binary data\n\n*Packet*\n\n```\n{ type: BINARY_ACK, namespace: \"/\", data: [\"bar\", \u003cBuffer \u003c01 02 03 04\u003e\u003e], id: 15 }\n```\n\n*Encoded*\n\n```\n61-15[\"bar\",{\"_placeholder\":true,\"num\":0}]\n\n+ \u003cBuffer \u003c01 02 03 04\u003e\u003e\n```\n\n#### Disconnection from a namespace\n\n- with the main namespace\n\n*Packet*\n\n```\n{ type: DISCONNECT, namespace: \"/\" }\n```\n\n*Encoded*\n\n```\n1\n```\n\n- with a custom namespace\n\n```\n{ type: DISCONNECT, namespace: \"/admin\" }\n```\n\n*Encoded*\n\n```\n1/admin,\n```\n\n\n## Sample session\n\nHere is an example of what is sent over the wire when combining both the Engine.IO and the Socket.IO protocols.\n\n- Request n°1 (open packet)\n\n```\nGET /socket.io/?EIO=4\u0026transport=polling\u0026t=N8hyd6w\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: text/plain; charset=UTF-8\n0{\"sid\":\"lv_VI97HAXpY6yYWAAAC\",\"upgrades\":[\"websocket\"],\"pingInterval\":25000,\"pingTimeout\":5000,\"maxPayload\":1000000}\n```\n\nDetails:\n\n```\n0           =\u003e Engine.IO \"open\" packet type\n{\"sid\":...  =\u003e the Engine.IO handshake data\n```\n\nNote: the `t` query param is used to ensure that the request is not cached by the browser.\n\n- Request n°2 (namespace connection request):\n\n```\nPOST /socket.io/?EIO=4\u0026transport=polling\u0026t=N8hyd7H\u0026sid=lv_VI97HAXpY6yYWAAAC\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: text/plain; charset=UTF-8\n40\n```\n\nDetails:\n\n```\n4           =\u003e Engine.IO \"message\" packet type\n0           =\u003e Socket.IO \"CONNECT\" packet type\n```\n\n- Request n°3 (namespace connection approval)\n\n```\nGET /socket.io/?EIO=4\u0026transport=polling\u0026t=N8hyd7H\u0026sid=lv_VI97HAXpY6yYWAAAC\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: text/plain; charset=UTF-8\n40{\"sid\":\"wZX3oN0bSVIhsaknAAAI\"}\n```\n\n- Request n°4\n\n`socket.emit('hey', 'Jude')` is executed on the server:\n\n```\nGET /socket.io/?EIO=4\u0026transport=polling\u0026t=N8hyd7H\u0026sid=lv_VI97HAXpY6yYWAAAC\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: text/plain; charset=UTF-8\n42[\"hey\",\"Jude\"]\n```\n\nDetails:\n\n```\n4           =\u003e Engine.IO \"message\" packet type\n2           =\u003e Socket.IO \"EVENT\" packet type\n[...]       =\u003e content\n```\n\n- Request n°5 (message out)\n\n`socket.emit('hello'); socket.emit('world');` is executed on the client:\n\n```\nPOST /socket.io/?EIO=4\u0026transport=polling\u0026t=N8hzxke\u0026sid=lv_VI97HAXpY6yYWAAAC\n\u003e Content-Type: text/plain; charset=UTF-8\n42[\"hello\"]\\x1e42[\"world\"]\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: text/plain; charset=UTF-8\nok\n```\n\nDetails:\n\n```\n4           =\u003e Engine.IO \"message\" packet type\n2           =\u003e Socket.IO \"EVENT\" packet type\n[\"hello\"]   =\u003e the 1st content\n\\x1e        =\u003e separator\n4           =\u003e Engine.IO \"message\" packet type\n2           =\u003e Socket.IO \"EVENT\" packet type\n[\"world\"]   =\u003e the 2nd content\n```\n\n- Request n°6 (WebSocket upgrade)\n\n```\nGET /socket.io/?EIO=4\u0026transport=websocket\u0026sid=lv_VI97HAXpY6yYWAAAC\n\u003c HTTP/1.1 101 Switching Protocols\n```\n\nWebSocket frames:\n\n```\n\u003c 2probe                                        =\u003e Engine.IO probe request\n\u003e 3probe                                        =\u003e Engine.IO probe response\n\u003e 5                                             =\u003e Engine.IO \"upgrade\" packet type\n\u003e 42[\"hello\"]\n\u003e 42[\"world\"]\n\u003e 40/admin,                                     =\u003e request access to the admin namespace (Socket.IO \"CONNECT\" packet)\n\u003c 40/admin,{\"sid\":\"-G5j-67EZFp-q59rADQM\"}       =\u003e grant access to the admin namespace\n\u003e 42/admin,1[\"tellme\"]                          =\u003e Socket.IO \"EVENT\" packet with acknowledgement\n\u003c 461-/admin,1[{\"_placeholder\":true,\"num\":0}]   =\u003e Socket.IO \"BINARY_ACK\" packet with a placeholder\n\u003c \u003cbinary\u003e                                      =\u003e the binary attachment (sent in the following frame)\n... after a while without message\n\u003e 2                                             =\u003e Engine.IO \"ping\" packet type\n\u003c 3                                             =\u003e Engine.IO \"pong\" packet type\n\u003e 1                                             =\u003e Engine.IO \"close\" packet type\n```\n\n## History\n\n### Difference between v5 and v4\n\nThe 5th revision (current) of the Socket.IO protocol is used in Socket.IO v3 and above (`v3.0.0` was released in November 2020).\n\nIt is built on top of the 4th revision of [the Engine.IO protocol](https://github.com/socketio/engine.io-protocol) (hence the `EIO=4` query parameter).\n\nList of changes:\n\n- remove the implicit connection to the default namespace\n\nIn previous versions, a client was always connected to the default namespace, even if it requested access to another namespace.\n\nThis is not the case anymore, the client must send a `CONNECT` packet in any case.\n\nCommits: [09b6f23](https://github.com/socketio/socket.io/commit/09b6f2333950b8afc8c1400b504b01ad757876bd) (server) and [249e0be](https://github.com/socketio/socket.io-client/commit/249e0bef9071e7afd785485961c4eef0094254e8) (client)\n\n\n- rename `ERROR` to `CONNECT_ERROR`\n\nThe meaning and the code number (4) are not modified: this packet type is still used by the server when the connection to a namespace is refused. But we feel the name is more self-descriptive.\n\nCommits: [d16c035](https://github.com/socketio/socket.io/commit/d16c035d258b8deb138f71801cb5aeedcdb3f002) (server) and [13e1db7c](https://github.com/socketio/socket.io-client/commit/13e1db7c94291c583d843beaa9e06ee041ae4f26) (client).\n\n\n- the `CONNECT` packet now can contain a payload\n\nThe client can send a payload for authentication/authorization purposes. Example:\n\n```json\n{\n  \"type\": 0,\n  \"nsp\": \"/admin\",\n  \"data\": {\n    \"token\": \"123\"\n  }\n}\n```\n\nIn case of success, the server responds with a payload contain the ID of the Socket. Example:\n\n```json\n{\n  \"type\": 0,\n  \"nsp\": \"/admin\",\n  \"data\": {\n    \"sid\": \"CjdVH4TQvovi1VvgAC5Z\"\n  }\n}\n```\n\nThis change means that the ID of the Socket.IO connection will now be different from the ID of the underlying Engine.IO connection (the one that is found in the query parameters of the HTTP requests).\n\nCommits: [2875d2c](https://github.com/socketio/socket.io/commit/2875d2cfdfa463e64cb520099749f543bbc4eb15) (server) and [bbe94ad](https://github.com/socketio/socket.io-client/commit/bbe94adb822a306c6272e977d394e3e203cae25d) (client)\n\n\n- the payload `CONNECT_ERROR` packet is now an object instead of a plain string\n\nCommits: [54bf4a4](https://github.com/socketio/socket.io/commit/54bf4a44e9e896dfb64764ee7bd4e8823eb7dc7b) (server) and [0939395](https://github.com/socketio/socket.io-client/commit/09393952e3397a0c71f239ea983f8ec1623b7c21) (client)\n\n\n### Difference between v4 and v3\n\nThe 4th revision of the Socket.IO protocol is used in Socket.IO v1 (`v1.0.3` was released in June 2014) and v2 (`v2.0.0` was released in May 2017).\n\nThe details of the revision can be found here: https://github.com/socketio/socket.io-protocol/tree/v4\n\nIt is built on top of the 3rd revision of [the Engine.IO protocol](https://github.com/socketio/engine.io-protocol) (hence the `EIO=3` query parameter).\n\nList of changes:\n\n- add a `BINARY_ACK` packet type\n\nPreviously, an `ACK` packet was always treated as if it may contain binary objects, with recursive search for such\nobjects, which could hurt performance.\n\nReference: https://github.com/socketio/socket.io-parser/commit/ca4f42a922ba7078e840b1bc09fe3ad618acc065\n\n### Difference between v3 and v2\n\nThe 3rd revision of the Socket.IO protocol is used in early Socket.IO v1 versions (`socket.io@1.0.0...1.0.2`) (released in May 2014).\n\nThe details of the revision can be found here: https://github.com/socketio/socket.io-protocol/tree/v3\n\nList of changes:\n\n- remove the usage of msgpack to encode packets containing binary objects (see also [299849b](https://github.com/socketio/socket.io-parser/commit/299849b00294c3bc95817572441f3aca8ffb1f65))\n\n### Difference between v2 and v1\n\nList of changes:\n\n- add a `BINARY_EVENT` packet type\n\nThis was added during the work towards Socket.IO 1.0, in order to add support for binary objects. The `BINARY_EVENT`\npackets were encoded with [msgpack](https://msgpack.org/).\n\n### Initial revision\n\nThis first revision was the result of the split between the Engine.IO protocol (low-level plumbing with WebSocket / HTTP\nlong-polling, heartbeat) and the Socket.IO protocol. It was never included in a Socket.IO release, but paved the way for\nthe next iterations.\n\n## Test suite\n\nThe test suite in the [`test-suite/`](https://github.com/socketio/socket.io-protocol/tree/main/test-suite) directory lets you check the compliance of a server implementation.\n\nUsage:\n\n- in Node.js: `npm ci \u0026\u0026 npm test`\n- in a browser: simply open the `index.html` file in your browser\n\nFor reference, here is expected configuration for the JavaScript server to pass all tests:\n\n```js\nimport { Server } from \"socket.io\";\n\nconst io = new Server(3000, {\n  pingInterval: 300,\n  pingTimeout: 200,\n  maxPayload: 1000000,\n  connectTimeout: 1000,\n  cors: {\n    origin: \"*\"\n  }\n});\n\nio.on(\"connection\", (socket) =\u003e {\n  socket.emit(\"auth\", socket.handshake.auth);\n\n  socket.on(\"message\", (...args) =\u003e {\n    socket.emit.apply(socket, [\"message-back\", ...args]);\n  });\n\n  socket.on(\"message-with-ack\", (...args) =\u003e {\n    const ack = args.pop();\n    ack(...args);\n  })\n});\n\nio.of(\"/custom\").on(\"connection\", (socket) =\u003e {\n  socket.emit(\"auth\", socket.handshake.auth);\n});\n```\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsocketio%2Fsocket.io-protocol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsocketio%2Fsocket.io-protocol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsocketio%2Fsocket.io-protocol/lists"}