209

I'm trying to get a list of all the sockets/clients that are currently connected.

io.sockets does not return an array, unfortunately.

I know I could keep my own list using an array, but I don't think this is an optimal solution for two reasons:

  1. Redundancy. Socket.IO already keeps a copy of this list.

  2. Socket.IO provides method to set arbitrary field values for clients (i.e: socket.set('nickname', 'superman')), so I'd need to keep up with these changes if I were to maintain my own list.

What should I do?

8
  • Can't you just convert io.sockets to an array? Commented Jul 3, 2011 at 17:15
  • 2
    In 0.7.6 io.sockets.sockets is a simple hash object id => socket Commented Jul 3, 2011 at 17:34
  • 1
    I noticed that, but it is acting strange (does not seem like standard socket objects). For example I tried: pastebin.com/fxuzVckS but it is saying the socket object does not contain a 'get' method. Commented Jul 3, 2011 at 17:59
  • 3
    socket is id, io.sockets.sockets[socket] is the socket. Commented Jul 3, 2011 at 18:08
  • 2
    First argument is err and if you're using memory store it's always null. .get('nickname', function(err, nickname) { ... }) Commented Jul 3, 2011 at 18:44

35 Answers 35

198

In Socket.IO 0.7 you have a clients method on the namespaces. This returns an array of all connected sockets.

API for no namespace:

var clients = io.sockets.clients(); var clients = io.sockets.clients('room'); // all users from room `room` 

For a namespace

var clients = io.of('/chat').clients(); var clients = io.of('/chat').clients('room'); // all users from room `room` 

Note: This solution only works with a version prior to 1.0

From 1.x and above, please refer to getting how many people are in a chat room in socket.io.

Sign up to request clarification or add additional context in comments.

8 Comments

I think they've dropped the clients method in 1.0... just checking that out at the moment...
They dropped nearly everything in 1.0 as it's a complete rewrite. But as 1.0 has been unreleased for years. In 1.0 you have to use the connected object of the namespace.
@3rdEden, what is the syntax for using the connected object of namespace ? var clients = io.sockets.connected(); obviously doesn't work. Thanks
TypeError: fn.bind is not a function
|
106

Socket.IO 1.4

Object.keys(io.sockets.sockets); gives you all the connected sockets.

Socket.IO 1.0

As of Socket.IO 1.0, the actual accepted answer isn't valid any more.

So I made a small function that I use as a temporary fix:

function findClientsSocket(roomId, namespace) { var res = [] // The default namespace is "/" , ns = io.of(namespace ||"/"); if (ns) { for (var id in ns.connected) { if(roomId) { var index = ns.connected[id].rooms.indexOf(roomId); if(index !== -1) { res.push(ns.connected[id]); } } else { res.push(ns.connected[id]); } } } return res; } 

The API for no namespace becomes:

// var clients = io.sockets.clients(); // becomes: var clients = findClientsSocket(); // var clients = io.sockets.clients('room'); // all users from room `room` // becomes var clients = findClientsSocket('room'); 

The API for a namespace becomes:

// var clients = io.of('/chat').clients(); // becomes var clients = findClientsSocket(null, '/chat'); // var clients = io.of('/chat').clients('room'); // all users from room `room` // becomes var clients = findClientsSocket('room', '/chat'); 

Also see this related question, in which I give a function that returns the sockets for a given room.

function findClientsSocketByRoomId(roomId) { var res = [] , room = io.sockets.adapter.rooms[roomId]; if (room) { for (var id in room) { res.push(io.sockets.adapter.nsp.connected[id]); } } return res; } 

Socket.IO 0.7

The API for no namespace:

var clients = io.sockets.clients(); var clients = io.sockets.clients('room'); // All users from room `room` 

For a namespace

var clients = io.of('/chat').clients(); var clients = io.of('/chat').clients('room'); // All users from room `room` 

Note: Since it seems the Socket.IO API is prone to breaking, and some solution rely on implementation details, it could be a matter of tracking the clients yourself:

var clients = []; io.sockets.on('connect', function(client) { clients.push(client); client.on('disconnect', function() { clients.splice(clients.indexOf(client), 1); }); }); 

3 Comments

@TylerScott Me too, especially given that this is not covered in their migration guide (unless I am missing something). socket.io/docs/migrating-from-0-9
how about for multiple node? because I using multiple node with redis store
@nha you answer is exactly, but it not working for multiple node with redis store server. from 1 node process, you can not check socket connected or not by using ns.connected[id]
48

After Socket.IO 1.0, we cannot use

io.sockets.clients(); 

or

io.sockets.clients('room'); 

any more.

Instead you can use the following:

var clients_in_the_room = io.sockets.adapter.rooms[roomId]; for (var clientId in clients_in_the_room ) { console.log('client: %s', clientId); // Seeing is believing var client_socket = io.sockets.connected[clientId]; // Do whatever you want with this } 

1 Comment

i change to var clients_in_the_room = io.sockets.adapter.rooms[roomId].sockets
39

Using Socket.IO 1.x:

Get an array of the connected clients:

io.engine === io.eio // => true Object.keys(io.engine.clients) // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ] Object.keys(io.eio.clients) // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ] 

Get the number of connected clients:

io.engine.clientsCount // => 2 io.eio.clientsCount // => 2 

Comments

33

It is very simple in Socket.IO 1.3:

io.sockets.sockets - is an array containing the connected socket objects.

If you stored the username in each socket, you can do:

io.sockets.sockets.map(function(e) { return e.username; }) 

Boom. You have the names of all connected users.

3 Comments

Thanks! +1 for simplicity. Do you know if there is any difference between this method and, say, Joseph Dykstra's answer? (Object.keys(io.engine.clients)
This doesn't work on v1.4.5. Still working on a solution
TypeError: io.sockets.sockets.map is not a function
33

Update Socket.IO v4.0+ (last checked Nov 6 2022)

I've tried all of the other answers... None of them worked, except this:

The easiest way to get all the connected sockets is through:

await io.fetchSockets() 

It returns an array of all connected sockets

Documentation

// Return all Socket instances const sockets = await io.fetchSockets(); // Return all Socket instances in the "room1" room of the main namespace const sockets = await io.in("room1").fetchSockets(); // Return all Socket instances in the "room1" room of the "admin" namespace const sockets = await io.of("/admin").in("room1").fetchSockets(); // This also works with a single socket ID const sockets = await io.in(theSocketId).fetchSockets(); 

Example usages

// With an async function const sockets = await io.fetchSockets() sockets.forEach(socket => { // Do something }); 
// Without an async function io.fetchSockets() .then((sockets) => { sockets.forEach((socket) => { // Do something }) }) .catch(console.log) 

5 Comments

Works really great on v4 . Thanks for explaining usages and tagging the documentation references.
It would be great if we have a method using iterator instead of getting the whole list in the memory for a large number of connections. Any suggestions?
const sockets = (await io.fetchSockets()).map(socket => socket.id); console.log(sockets);
for console log purposes: (await io.fetchSockets()).map( skt => console.log( skt.id ))
This should be the top answer.
23

I've gone through this pain today. Socket.IO would be much better if they could make a proper documentation for their API.

Anyway, I tried to look into io.sockets and found a number of options we can use:

io.sockets.connected //Return {socket_1_id: {}, socket_2_id: {}} . This is the most convenient one, since you can just refer to io.sockets.connected[id] then do common things like emit() io.sockets.sockets //Returns [{socket_1}, {socket_2}, ....]. Can refer to socket_i.id to distinguish io.sockets.adapter.sids //Return {socket_1_id: {}, socket_2_id: {}} . Looks similar to the first one but the object is not actually the socket, just the information. // Not directly helps but still relevant io.sockets.adapter.rooms // Returns {room_1_id: {}, room_2_id: {}} io.sockets.server.eio.clients // Return client sockets io.sockets.server.eio.clientsCount // Return number of connected clients 

Also, do note that when using socket.io with namespace, the above methods will break since io.sockets becomes an array instead of an object. To resolve, just replace io.sockets by io (i.e., io.sockets.connected becomes io.connected, io.sockets.adapter.rooms becomes io.adapter.rooms...)

It was tested on Socket.IO 1.3.5.

1 Comment

@Зелёный It will work if you're not using namespace. If you're using namespace, change to io.server.eio.clientsCount
20

Version 2.x

In version 2.x you specify the namespace/room/node you are querying against.

As with broadcasting, the default is all clients from the default namespace ('/'):

const io = require('socket.io')(); io.clients((error, clients) => { if (error) throw error; console.log(clients); // => [6em3d4TJP8Et9EMNAAAA, G5p55dHhGgUnLUctAAAB] }); 

Gets a list of client IDs connected to specific namespace (across all nodes if applicable).

const io = require('socket.io')(); io.of('/chat').clients((error, clients) => { if (error) throw error; console.log(clients); // => [PZDoMHjiu8PYfRiKAAAF, Anw2LatarvGVVXEIAAAD] }); 

An example to get all clients in namespace's room:

const io = require('socket.io')(); io.of('/chat').in('general').clients((error, clients) => { if (error) throw error; console.log(clients); // => [Anw2LatarvGVVXEIAAAD] }); 

This is from the official documentation: Socket.IO Server-API

4 Comments

is there a way to view all socket objects? for example, if i add a socket.username property to each socket on connecting, is there a way i can view all of these socket objects (including the custom properties i add to each socket)? (for reference, i am currently using a global object variable to store additional socket information when a client connects - so not asking how to set that up - just interested in knowing if there is a way to view all socket objects by 'default').
hmm, per this answer, i think you can see all connected sockets with console.log(io.sockets.connected) - it seems to be an object where each property value is a "socket object" which contains these properties nsp, server, adaptor, id ( a string), client, conn, rooms, acks, connected, disconnected, handshake, fns, flags, _rooms, _events, _eventsCount and finally username which is the custom property i add to each socket on connection.
What is "+2.0"? After 2.0 (not including 2.0)?
Edited to specify as v2.x. Also edited broken link to Socket.IO's v2.x Server API documentation.
17

I think we can access the socket object from the server, and you can assign the nickname, and point its socket id,

io.sockets.on('connection',function(socket){ io.sockets.sockets['nickname'] = socket.id; client.on("chat", function(data) { var sock_id = io.sockets.sockets['nickname'] io.sockets.sockets[sock_id].emit("private", "message"); }); }); 

On disconnect please remove the nickname from io.sockets.sockets.

1 Comment

what is the purpose of 'client.on'? Can you use your code like this (only accepting data from 1 socket)?: io.sockets.sockets[sock_id].on('newmessage', function (data) { console.log(data) });
9

This is the best way to access it in Socket.IO 1.3:

Object.keys(socket.adapter.rooms[room_id]) 

2 Comments

please let me share this example , var room = io.sockets.adapter.rooms[room_id]; var connections = _.map(Object.keys(room), function(socketId){ return (io.sockets.connected[socketId].connected == true) });
Why is it the best way? What makes it the best way? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
9

Version 4.0 and later (2021)

None of the answers worked for me. I will spare you the pain. Their API and documentation have changed greatly since 1.0 onward.

Server API: all available options

But you need to dig deeper here.

// Return all Socket instances var clients = io.sockets; clients.sockets.forEach(function(data, counter) { //console.log(data); // Maps var socketid = data.id; // Log ids var isConnected = data.connected // true, false; }); 

UPDATE 2023 - Get All Connected Users

I want to add to this answer by showing you how you can attach the userid to the socketid to create persistence if you need it to use it in a project(ie: private messaging).

client.js (client-side)

/*** * * * getConnectedUsers * * * */ function getConnectedUsers(){ /** * * * STEP 1 * GET * * */ // var userID = localStorage.getItem('userid');//this typically would be the unique id from your database. Set this variable at login() //set-username socket.auth = { userID }; //console.log(socket.auth); // //get-connected-socket-users socket.emit('get-connected-socket-users',{ userid:userID }); } /** * * * STEP 2 * SET * use this for instant communication * */ socket.on('connected-socket-users',function(data){ //console.log(data); var connectedUsers = JSON.stringify(data); localStorage.setItem('connectedUsers',connectedUsers); //console.log(localStorage.getItem('connectedUsers')); }); 

server.js (server side)

/** * * * GET ALL CONNECTED USERS * * */ socket.on('get-connected-socket-users',function(data){ // //variables var userid = data.userid; socket.username = userid; //console.log(io.sockets); //console.log(userid); /** * * GET ALL CONNECTED USERS * */ const users = []; var clients = io.sockets; clients.sockets.forEach(function(data,counter){ users.push({ userSocketID: data.id, username: data.username, }); }); //console.log(users); //var handle = setInterval(function(){ socket.emit("connected-socket-users", users); }, 3000); // When you want to cancel it: //clearInterval(handle); //handle = 0; // I just do this so I know I've cleared the interval }); 

1 Comment

const sockets = Array.from(io.sockets.sockets).map(socket => socket[0]); console.log(sockets);
5

For anyone that just wants a count of the connected clients, I believe this will do it:

io.sockets.manager.server.connections

3 Comments

isnt the connected clients count, tested. (bit more)
in order to get an accurate count use io.sockets.clients().length
Currently both io.sockets.manager.server.connections and io.sockets.clients().length dont work. This worked for me - For count only - io.engine.clientsCount and for the list of clients - io.engine.clientsCount. Since it has stayed this way for over 3 years. Seems like a reliable way to get the connection info. (Based on Joseph Dykstra's answer)
5

In Socket.IO 1.4

To get the array of all connected users:

var allConnectedClients = Object.keys(io.sockets.connected); // This will return the array of SockeId of all the connected clients 

To get the count of all clients:

var clientsCount = io.engine.clientsCount ; // This will return the count of connected clients 

1 Comment

I confirm that this works in version 1.5.1 of socket.io
5

Socket.IO 1.4.4

Sample code for you.

function get_clients_by_room(roomId, namespace) { io.of(namespace || "/").in(roomId).clients(function (error, clients) { if (error) { throw error; } console.log(clients[0]); // => [Anw2LatarvGVVXEIAAAD] console.log(io.sockets.sockets[clients[0]]); // Socket detail return clients; }); } 

Comments

3

As of Socket.IO 1.5, note the change from indexOf which appears to de deprecated, and replaced by valueOf

function findClientsSocket(roomId, namespace) { var res = []; var ns = io.of(namespace ||"/"); // The default namespace is "/" if (ns) { for (var id in ns.connected) { if (roomId) { //var index = ns.connected[id].rooms.indexOf(roomId) ; var index = ns.connected[id].rooms.valueOf(roomId) ; //Problem was here if(index !== -1) { res.push(ns.connected[id]); } } else { res.push(ns.connected[id]); } } } return res.length; } 

For Socket.IO version 2.0.3, the following code works:

function findClientsSocket(io, roomId, namespace) { var res = [], ns = io.of(namespace ||"/"); // the default namespace is "/" if (ns) { for (var id in ns.connected) { if(roomId) { // ns.connected[id].rooms is an object! var rooms = Object.values(ns.connected[id].rooms); var index = rooms.indexOf(roomId); if(index !== -1) { res.push(ns.connected[id]); } } else { res.push(ns.connected[id]); } } } return res; } 

1 Comment

but socket.io version is not 1.5 yet ! It is 1.4.8 now
3

Socket.IO 3.0

io.in('room1').sockets.sockets.forEach((socket, key) => { console.log(socket); }) 

It gets all socket instances in room1.

1 Comment

The best answer for version 4.x. Thanks!
2

io.sockets.sockets.keys()

This helps me.

1 Comment

Can you elaborate? How does this get "a list of all the sockets/clients that are currently connected"? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
2

In Socket.IO 1.3, I've accomplished this in two lines:

var usersSocketIds = Object.keys(chat.adapter.rooms['room name']); var usersAttending = _.map(usersSocketIds, function(socketClientId){ return chat.connected[socketClientId] }) 

Comments

2

Socket.io 1.7.3 or later:

function getConnectedList () { let list = [] for (let client in io.sockets.connected) { list.push(client) } return list } console.log(getConnectedList()) // returns [ 'yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB' ] 

Comments

2

For version 2.3, this works and it will get you the socket too. It seems to me that socketIo is changing too fast and to much with to little readable documentation after using it for a while.

ioSite.of('/').in(roomId).clients((error, clients) => { if (error) throw error; for (var i=0; i<clients.length; i++) { clientId = clients[i]; console.log(clientId); // Load the socket of your namespace var socket = ioSite.of('/').in(roomId).connected[clientId] console.log(socket.constructor.name); console.log(socket.id); } }); 

Still this does not feel right, as I have always this feeling with Socket.IO somehow.

Comments

2

For cluster mode, using Redis adapter:

io.in(<room>).clients(function(err, clients) { }); 

As each socket is itself a room, one can find whether a socket exist using the same.

Comments

2

namespace.allSockets()

It returns a Promise<Set<SocketId>>.

io.allSockets(): All connected socket ids in the main namespace

io.in('room').allSockets(): All connected ids in the 'room'

io.of('/namespace').allSockets(): All connected ids in '/namespace' (you can also combine this with rooms)

1 Comment

This works in both Socket.IO v3.x and v4.x. If you want to get the actual Socket objects from the Set of IDs received from allSockets() you can use io.of('/namespace').sockets to get a Map of all Socket instances connected to a namespace so io.of('/namespace').sockets.get(socketId) gets the Socket instance matching the ID.
2

To get a list of socket id's, you can do:

[...io.sockets.sockets].map(s => s[0]); 

To get the socket object, do:

[...io.sockets.sockets].map(s => s[1]); 

Comments

1

As of version 1.5.1, I'm able to access all the sockets in a namespace with:

var socket_ids = Object.keys(io.of('/namespace').sockets); socket_ids.forEach(function(socket_id) { var socket = io.of('/namespace').sockets[socket_id]; if (socket.connected) { // Do something... } }); 

For some reason, they're using a plain object instead of an array to store the socket IDs.

2 Comments

This one works. An empty string in io.of('') works without namespaces.
@KirályIstván I haven't looked into this for a while now, but I think you can completely remove the of() chained call in that case.
1

I believe you can access this from the socket's manager property:

var handshaken = io.manager.handshaken; var connected = io.manager.connected; var open = io.manager.open; var closed = io.manager.closed; 

1 Comment

3rdEden's answer didn't work for me as there are issues with the array returning disconnected clients, which throws off the count. Object.keys(io.manager.open).length turned out to be the most reliable count in my experience. io.of('/namespace').manager.open if you're using namespaces.
1

I saw a lot of good answers here and many were quite useful, but not quite what I needed. I am using sockets for a pubsub feature in which an interested client can listen to any changes in a given record.

My specific issue was that the same socket was joining the same room several times. The solution to this was to check if the socket had the room inside its rooms property already.

var room = myObj.id.toString(); if (socket.rooms.indexOf(room) === -1) { socket.join(room); socket.emit('subscribed', {to : room}); } else { console.log("Already in room"); } 

4 Comments

I think it's possible to avoid that 'if' statement, if you make client join the room upon socket connection.
Where does myObj come from? How did you arrive at that value?
@MikeDraper myObject is the record in a database that acts as a channel. What this solves is the case where you want all your clients to be updated whenever a change in the database happens, for instance a user updates its name and all connected clients get an update. So I create a room for that instance id, given that it is unique (BSON). It is a very specific value for my use case, so I'm sorry If I caused any confusion. Let me know if you need help :)
@JMR due to the nature of my app it happened that a socket got subscribed more than once, that's why I had to add that check.
1

This is the simplest way in Socket.IO 1.0 or later, if you are not using namespaces or rooms.

io.nsps["/"].sockets.length 

This looks at the default namespace and determines the length of the sockets array, without needing to use Object.keys().

Comments

1

If the project has a socket.io cluster this means the socket.io-redis adapter is being used.

If the case is like the above, getting the all connected sockets id processes must be applied via the socket.io-redis adapter. The examples below might be used for this;

io.of('/').adapter.clients(function (err, clients) { console.log("clients: ", clients); // an array containing all connected socket ids }); io.of('/').adapter.allRooms(function (err, rooms) { console.log("all rooms: ", rooms); }); 

Please visit socket.io-redis github page for more details.

Comments

1

Socket.IO 4.x

const socketsOnDefaultNamespace = io.of('/').sockets.size; console.log("Number of clients connected: ", socketsOnDefaultNamespace); const socketsInARoomInSomeNamespace = io .of('/someNamespace') .in('/someRoomname') .fetchSockets() .then((room) => { console.log("clients in this room: ", room.length); }); 

You can read more in the documentation.

Comments

0

v.10

var clients = io.nsps['/'].adapter.rooms['vse']; /* 'clients' will return something like: Room { sockets: { '3kiMNO8xwKMOtj3zAAAC': true, FUgvilj2VoJWB196AAAD: true }, length: 2 } */ var count = clients.length; // 2 var sockets = clients.map((item)=>{ // all sockets room 'vse' return io.sockets.sockets[item]; }); sample >>> var handshake = sockets[i].handshake; handshake.address .time .issued ... etc. 

3 Comments

It would be good if you could add some context why 'This is the best way' and how your answer adds anything to all of the many answers above. Code is something, but an answer should also have some explanation. As you can see there are many other answers to this question. Your answer must brings something more to the subject, otherwise, it is redundant.
With socket.io 2.1.1 , I get TypeError: clients.map is not a function and although it looks promising, i'm not entirely sure what the above example will achieve - i was hoping it would automagically create an array of client objects with usernames included :).
What do you mean by "v.10"? I don't think version 10 has been released yet. Do you mean "v. 1.0"?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.