Socket.IO - how do I get a list of connected sockets/clients?

node.jssocket.io

node.js Problem Overview


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 don't think this is an optimal solution for 2 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.

Help?

node.js Solutions


Solution 1 - node.js

In Socket.IO 0.7 you have a clients method on the namespaces, this returns a 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`

Hopes this helps someone in the future

> NOTE: This Solution ONLY works with version prior to 1.0


UPDATED 2020 Mar 06

From 1.x and above, please refer to this link: https://stackoverflow.com/questions/9352549/getting-how-many-people-are-in-a-chat-room-in-socket-io#24425207

Solution 2 - node.js

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 anymore. 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;
}

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');

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

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);
    });
});

Solution 3 - node.js

After socket.io 1.0 we cannot use

io.sockets.clients(); 
or
io.sockets.clients('room'); 

anymore. 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
}

Solution 4 - node.js

Using Socket.IO 1.x:

Get 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

Solution 5 - node.js

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.

Solution 6 - node.js

I've gone through this pain today. Socket.io will 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 ...)

Tested on socket.io 1.3.5

Solution 7 - node.js

Version +2.0

In version +2.0 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

Solution 8 - node.js

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.

Solution 9 - node.js

This is the best way to access it in socket.io 1.3

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

Solution 10 - node.js

2021 Update V4.0+

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

Server Api all availble 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;

});

Solution 11 - node.js

Update Socket.io v4.0+

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 async function

 const sockets = await io.fetchSockets()
 sockets.forEach(socket => {
    //do something
 });
//without async function

io.fetchSockets()
.then((sockets) => {
  sockets.forEach((socket) => {
    //do something
  })
})
.catch(console.log) 

Solution 12 - node.js

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

io.sockets.manager.server.connections

Solution 13 - node.js

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;
        });
    }

I think will help someone this code block.

Solution 14 - node.js

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


   

Solution 15 - node.js

As of socket.io 1.5, note the change from indexOf which appears to de depreciated, 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;
}

Solution 16 - node.js

on socket.io 1.3 i've accomplished this in 2 lines

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

Solution 17 - node.js

Socket.io 1.7.3(+) :

function getConnectedList ()
{
let list = []

for ( let client in io.sockets.connected )
{
    list.push(client)
}

return list

}

console.log( getConnectedList() )

// returns [ 'yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB' ]

Solution 18 - node.js

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

Solution 19 - node.js

For cluster mode, using redis-adaptor

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

});

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

Solution 20 - node.js

[email protected]

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

all socket instance in room1

Solution 21 - node.js

namespace.allSockets()

Returns Promise>

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)

Solution 22 - node.js

io.sockets.sockets.keys()

This helps me.

Solution 23 - node.js

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;

Solution 24 - node.js

I see a lot of good answers here and many where 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");
}

Hope this helps someone.

Solution 25 - node.js

This is the simplest way in Socket.IO 1.0+, 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()

Solution 26 - node.js

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.

Solution 27 - node.js

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

If the case like the above, getting the all connected sockets id process must be applied via 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.

Solution 28 - node.js

to get 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]);

Solution 29 - node.js

Here is a quick way to convert the hash of connected sockets from a namespace into an array using ES6 generators (applies to socket.io >= v1.0.0):

io.on('connection', function(socket) {
  var hash = io.of('/').connected
  var list = null
  
  hash[Symbol.iterator] = function*() {
    // for..of loop to invoke Object.keys() default iterator
    // to get the array values instead of the keys
    for(var id of Object.keys(hash)) yield hash[id]
  }

  list = [...hash]
  console.log(Array.isArray(list)) // true
})

Solution 30 - node.js

I don't know if this is still going. But something like this is what I ended up using (I keep a session object on each connected socket, which in turn contains the username and other info:

var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
	return io.sockets.connected[socketId].session.username;
});

Solution 31 - node.js

[email protected]

I used Object.Keys to get the array of socket connected. Then in the same array iterate with map function to build a new array of objects

var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
    return { socket_id : socketId, socket_username: io.sockets.connected[socketId].username };
});

// test
console.log(connectedUsers);

Perhaps this answer can help to get socket id/username array.

Solution 32 - node.js

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.

Solution 33 - node.js

for socket.io version 4.0.0

On server side to list some property of all active sockets I use this:

function listSocketsProperty(myProperty){
  let sck = io.sockets.sockets
  const mapIter = sck.entries()
  while(1){
    let en = mapIter.next().value?.[0]
    if(en) console.log( sck.get(en)[myProperty] )
    else break
  }
}

Explanation:

sck=io.sockets.sockets is a Map object.

The entries() method returns a new Iterator object that contains the [key, value] pairs for each element in the Map object.

en=mapIter.next().value?.[0] gets key - the first element of pair.

If there is no more to iterate, en becomes undefined and this breaks the while loop.

Example:

My sockets have property 'playerName', and I want to list names of all active players in all rooms. To do that, I simply call function:

listSocketsProperty('playerName')

and get in console something like this:

John
Peter
Zoran
etc.

Solution 34 - node.js

Socket.io v4.x

const socketsOnDefaultNamespace = io.of('/').sockets.size;
console.log("No 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 here: docs

Solution 35 - node.js

Easy ref for Socket.io v4

socket.server.eio.clients

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndy HinView Question on Stackoverflow
Solution 1 - node.js3rdEdenView Answer on Stackoverflow
Solution 2 - node.jsnhaView Answer on Stackoverflow
Solution 3 - node.jssalihcenapView Answer on Stackoverflow
Solution 4 - node.jsJoseph DykstraView Answer on Stackoverflow
Solution 5 - node.jsor29544View Answer on Stackoverflow
Solution 6 - node.jsThanh NguyenView Answer on Stackoverflow
Solution 7 - node.jsJohn GaltView Answer on Stackoverflow
Solution 8 - node.jssunil n joseView Answer on Stackoverflow
Solution 9 - node.jsksloanView Answer on Stackoverflow
Solution 10 - node.jsGroguView Answer on Stackoverflow
Solution 11 - node.jsCoder Gautam YTView Answer on Stackoverflow
Solution 12 - node.jscrickeysView Answer on Stackoverflow
Solution 13 - node.jsTiago ZamperiniView Answer on Stackoverflow
Solution 14 - node.jsKIAView Answer on Stackoverflow
Solution 15 - node.jsMoleIsKingView Answer on Stackoverflow
Solution 16 - node.jsCoelhoneView Answer on Stackoverflow
Solution 17 - node.jsAlexandre DaubricourtView Answer on Stackoverflow
Solution 18 - node.jsJoris CeelenView Answer on Stackoverflow
Solution 19 - node.jsAnuj NautiyalView Answer on Stackoverflow
Solution 20 - node.jsAtila PehlivanView Answer on Stackoverflow
Solution 21 - node.jsM. Emre YalçınView Answer on Stackoverflow
Solution 22 - node.jsg721View Answer on Stackoverflow
Solution 23 - node.jsDan SteeleView Answer on Stackoverflow
Solution 24 - node.jsGus OrtizView Answer on Stackoverflow
Solution 25 - node.jssuncannonView Answer on Stackoverflow
Solution 26 - node.jsrppcView Answer on Stackoverflow
Solution 27 - node.jsefkanView Answer on Stackoverflow
Solution 28 - node.jsMarcos VeniciusView Answer on Stackoverflow
Solution 29 - node.jsmorganneyView Answer on Stackoverflow
Solution 30 - node.jsdiazd2View Answer on Stackoverflow
Solution 31 - node.jsjvaldezbView Answer on Stackoverflow
Solution 32 - node.jsArk IvView Answer on Stackoverflow
Solution 33 - node.jsZoranView Answer on Stackoverflow
Solution 34 - node.jsIsaac PakView Answer on Stackoverflow
Solution 35 - node.jsCrispyView Answer on Stackoverflow