SkillAgentSearch skills...

Geckos.io

🦎 Real-time client/server communication over UDP using WebRTC and Node.js http://geckos.io

Install / Use

/learn @geckosio/Geckos.io
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<div align="center"> <a href="http://geckos.io"> <img src="readme/logo-256.png" alt="logo" width="128"> </a>

geckos.io

Geckos.io offers real-time client/server communication over UDP using WebRTC and Node.js

Geckos.io fits perfectly with your next HTML5 real-time multiplayer games or chat app.

NPM version Github Workflow Github Workflow Downloads Node version Codecov ES Modules Badge

</div>

:mega: Version 3 Available!

Version 3 of geckos.io is based on node-datachannel@0.5.x and only supports ESM and Node.js >=16. There are no other breaking changes.

Version 2

Version 2 has huge performance improvements. I switched from wrtc to node-datachannel, which is much lighter and faster compared to wrtc.

Geckos.io is now shipped as ECMAScript modules and will only support Node.js ^14.15 and >=16.

Install it

 npm i @geckos.io/client @geckos.io/server

Want to know more? Join the discussions!


Who should NOT use this library?

  • People who have never build a multiplayer game, should probably use a library like socket.io instead, since there are way more examples/tutorial available.
    Socket.io and geckos.io use a similar API. The switch from socket.io to geckos.io should be easy.

  • People who have no experiences setting up their own servers with UDP port forwarding, should probably look for a simple solution like websocket, although it is slower.

Menu

What is it made for?

It's designed specifically for your HTML5 real-time multiplayer games by lowering the average latency and preventing huge latency spikes. It allows you to communicate with your node.js server via UDP, which is much faster than TCP (used by WebSocket). Take a look at the comparison video between UDP and TCP. https://youtu.be/ZEEBsq3eQmg

<a href="https://youtu.be/ZEEBsq3eQmg"><img src="./readme/thumbnail.png" width="320"></a>

Getting Started

First things first, install it via npm:

npm install @geckos.io/client @geckos.io/server

And now, read the Documentation.

Btw, make sure you also check out enable3d.io.


Changelog

New in version 2.3.0

Multiplexing

When true (default), the first available port in the port range will be used for all connections, instead of assigning a new port for each connection.
Thanks to @arthuro555 and @paullouisageneau.

// server.js
const io = geckos({
  multiplex: true // default
})

New in version 1.7.1

You can now pass a more complex url to the client when you set port to null. This is useful if, for example, you use the geckos.io server behind a proxy.

// client.js

// default is
const channel = geckos({
  url: `${location.protocol}//${location.hostname}`,
  port: 9208
})

// connect to http://1.2.3.4:3000
const channel = geckos({
  url: 'http://1.2.3.4',
  port: 3000
})

// connect to https://geckos.example.com:9208
const channel = geckos({
  url: 'https://geckos.example.com',
  port: 9208 // not required, since 9208 is the default
})

// connect to https://api.example.com:3000/geckos
const channel = geckos({
  url: 'https://api.example.com:3000/geckos',
  port: null
})

// connect to https://api.example.com/geckos
const channel = geckos({
  url: 'https://api.example.com/geckos',
  port: null
})

New in version 1.7.0

Custom Port Range

Allows you to set a custom port range for the WebRTC connection.

// server.js
const io = geckos({
  portRange: {
    min: 10000,
    max: 20000
  }
})

New in version 1.6.0

Connections Manager

You now have access to the connections manager.

// get any channel by its ID via the connectionsManager
const connection = io.connectionsManager.getConnection(channel.id)
if (connection) {
  // here, you could emit a message ...
  connection.channel.emit('chat message', 'You have been kicked for cheating!')
  // ... or close the channel
  connection.channel.close()
}

Raw messages from the io scope

Finally you can send rawMessages from the io scope.

server

// emit a raw message to all channels
io.raw.emit(rawMessage)

// emit a raw message to a specific room
io.raw.room('roomId').emit(rawMessage)

Authorization and Authentication

The client is now able to send a authorization header with the connection request. If the authorization fails, the server will respond with 401 (unauthorized).

Whatever you add to the option authorization (must be a string) will be sent as a Authorization request header. You could, for example, send Basic base64-encoded credentials, Bearer tokens or a simple string, as in the example below.

Read more about HTTP authentication here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization.

client

const username = 'Yannick'
const password = '12E45'
const auth = `${username} ${password}` // 'Yannick 12E45'
const channel = geckos({ authorization: auth })

channel.onConnect(error => {
  if (error) {
    console.error('Status: ', error.status)
    console.error('StatusText: ', error.statusText)
  }
  console.log(channel.userData) // { username: 'Yannick', level: 13, points: 8987 }
})

server

const io: GeckosServer = geckos({
  /**
   * A async function to authenticate and authorize a user.
   * @param auth The authentication token
   * @param request The incoming http request
   * @param response The outgoing http response
   */
  authorization: async (auth: string | undefined, request: http.IncomingMessage, response: http.OutgoingMessage) => {
    const token = auth.split(' ') // ['Yannick', '12E45']
    const username = token[0] // 'Yannick'
    const password = token[1] // '12E45'

    // Use "request.connection.remoteAddress" to get the users ip.
    // ("request.headers['x-forwarded-for']" if your server is behind a proxy)

    // add a custom response header if you want
    response.setHeader(
      'www-authenticate',
      'Bearer realm="example", error="invalid_token", error_description="The access token expired"'
    )

    // reach out to a database if needed (this code is completely fictitious)
    const user = await database.getByName(username)

    // whatever you return here, will later be accessible via channel.userData to authenticate the user
    if (user.username === username && user.password === password)
      return { username: user.username, level: user.level, points: user.points }

    // if you return true, you will authorize the connection, without adding any data to channel.userData
    return true

    // if you return false, the server will respond with 401 (unauthorized)
    return false

    // if you return a number between 100 and 599, the server will respond with the respective HTTP status code
    return 400 // will return 400 (Bad Request)
    return 404 // will return 404 (Not Found)
    return 500 // will return 500 (Internal Server Error)
    // and so on ...
  },
  cors: { allowAuthorization: true } // required if the client and server are on separate domains
})

io.onConnection((channel: ServerChannel) => {
  console.log(channel.userData) // { username: 'Yannick', level: 13, points: 8987 }
})

New in version 1.5.0

New autoManageBuffering option

By default the RTCDataChannel queues data if it can't be send directly. This is very bad for multiplayer games, since we do not want to render old state. In version 1.5.0, the option autoManageBuffering was added. It is set to true by default. If autoManageBuffering is on, Geckos.io will prefer to drop messages instead of adding them to the send queue. (Messages with the option { reliable: true }, will still be added to the queue)

The problem with the queue while gaming?

If you send 30Kbytes @60fps and the client only has a 10Mbit connection, he can never receive all messages. So it is necessary to drop some of them, which will be done automatically with autoManageBuffering.
Another good solution to this problem would be to decrease the send rate for that specific client. Use the new channel.onDrop(drop => {}) method to track dropped messages. If, for example, you notice t

View on GitHub
GitHub Stars1.5k
CategoryDevelopment
Updated2h ago
Forks91

Languages

TypeScript

Security Score

100/100

Audited on Mar 27, 2026

No findings