U.chat() and the room object
U.chat(), the entry point for page scripts, and the values and functions of the room object that event callbacks receive.
Last updated October 17, 2026
On this page
A page script picks a chat room with U.chat() and receives the room object as the first argument of event callbacks. This page is the authoritative list for both. For event names and data, see Events; for channels (room.plugin), see Channel API and limits; for the skin UI (room.skin), see Skin UI API.
U.chat()
| Call | Returns |
|---|---|
U.chat('my-room') — room not installed yet |
Registrar { on, off } |
U.chat('my-room') — installed room |
That room's room object (including on, off) |
U.chat('*') |
Registrar for all rooms { on, off } |
Either way, you can attach events with .on(name, callback).
U.chat('my-room').on('after.join', function (room, data) {
room.print('Welcome, ' + data.my.nick + '.');
});
Uis created by uchat.js. Because uchat.js loads withasync, code that runs before it needs the pre-registration snippet. See Async loading and multiple chat rooms.- While the entry check (bot check) screen is shown,
U.chat('my-room')may returnundefined. Put code that runs right after page load inside the pre-registration snippet.
on / off
| Function | Arguments | Description |
|---|---|---|
on(name, fn) |
Event name (name#tag allowed), fn(room, data) |
Registers a callback. For after.create, if the room is already ready, it is called once immediately |
off(name) |
'name', '#tag', 'name#tag' |
Removes matching registrations |
off argument |
Removes |
|---|---|
'after.message' |
All registrations for that event (with or without a tag) |
'#stats' |
All registrations tagged stats |
'after.message#stats' |
Only registrations with exactly that name |
U.chat('*').off(...)also removes per-room registrations made withU.chat('my-room')orroom.on. Use a unique tag so you do not remove other scripts' registrations.U.chat('my-room').off(...)androom.off(...)remove only registrations made on that room.'*'registrations remain.- Do not call
off()with no arguments. It throws an error if there are registrations to remove. - Callbacks for the same event are called in the order they were registered. An exception in a callback is logged to the console, and the next callback is still called.
room values
| Name | Type | Description |
|---|---|---|
room.id |
String | Chat room ID |
room.my |
User object | Your own info. Empty object before entering (after.join) |
room.info |
Object | Chat room info. Empty object before entering. See room.info below |
room.user |
{ list, get } |
Connected users. See room.user below |
room.setting |
{ get, set, save, data } |
User settings stored in this browser. See room.setting below |
room.plugin |
Object | Channels. Channel API and limits |
room.action |
Object | Sending and commands. See room.action below |
room.skin |
Object | Skin UI API. Skin UI API |
room.skin.arguments |
Object | Admin page skin settings merged with the skin_arguments attribute |
room.agent |
{ userAgent, charset, mobile, android, ios, webkit } |
Browser info. userAgent is lowercase; webkit is a version number or false |
room.language |
{ system, error } |
Notice and error strings for the current language. Error strings are room.language.error[code] |
room.locale |
String | The resolved UI language code (ko, en, ja). Empty string before the language pack loads |
User object
room.my, room.user.get(), event data.user, and so on all have the same shape.
| Key | Type | Description |
|---|---|---|
nick |
String | Nickname |
id |
String | Member ID (member integration). Empty if none |
level |
Number/String | Level (member integration) |
auth |
Number | 0 guest, 1 member, 2 moderator, 3 admin, 4 server (sent via REST API or a saved channel value; nick and similar fields are empty in this case) |
icons |
String | List of icon URLs (the icons value from member integration) |
nickcon |
String | Image URL shown instead of the nickname |
connected |
String | Entry time 'YYYY-MM-DD HH:MM:SS' (in the viewer's time zone) |
time |
Number | Entry time (Unix seconds) |
mute |
0/1 |
1 while muted |
session |
String | Session identifier (hex). Used as the basis for ignoring and granting permissions |
profileimg |
String | Profile image URL (only when present) |
room.info
| Key | Description |
|---|---|
id, name |
Chat room ID and name |
mode |
0 normal, 1 private channel, 4 channel chat room |
created |
Creation time 'YYYY-MM-DD HH:MM:SS' |
frozen |
1 if the room was frozen when you entered. It does not change when the room is frozen or unfrozen, so check with system events (frozen, unfrozen) |
whisper, call, individual, font |
Whether whisper, call, private channel, and font styling are enabled (0/1) |
userLinkage |
1 if member integration is on |
slowSeconds |
Slow mode interval (seconds). 0 when off |
When chat room settings change, only the changed keys are merged into room.info, and an update event is fired.
room.user
| Name | Description |
|---|---|
room.user.get(nick) |
Finds a user object by nickname. undefined if not found |
room.user.list |
Currently connected users. It is an object, not an array, and the keys are escape(nickname) |
var user = room.user.get('홍길동');
if (user && user.auth >= 2) room.print('This user is a moderator or admin.');
- Use
user.getto look up by nickname. The keys ofuser.listare encoded withescape(), so a Korean nickname used as-is will not be found. user.getmay also return users who are not currently connected, such as people you saw in messages. Checkuser.listto see whether someone is connected.user.listchanges only when join and leave notifications (user.join,user.quit) arrive. In rooms where the user list is open in the default skin or where 100 or more people are connected, these notifications do not arrive, souser.listmay stay frozen at how it looked when you entered. → Events
room functions
| Function | Returns | Description |
|---|---|---|
room.print(html) |
— | Shows a notice line as HTML on your screen only. Only elements that can run scripts are removed, so escape user input yourself. A system event (type: 'notice') also fires |
room.on(name, fn) |
room |
Registers an event for this room only. Same as on / off |
room.off(name) |
— | Removes registrations for this room |
room.now() |
Number | Current time by the server clock (milliseconds, rounded to whole seconds) |
room.getTimeStamp([sec]) |
String | Converts Unix seconds to 'YYYY-MM-DD HH:MM:SS' (in the viewer's time zone). If omitted, uses the current server time |
room.reload() |
— | Removes the chat room and reinstalls it in the same place. Events registered on this room (U.chat('my-room'), room.on) are also removed, so you must register them again. '*' registrations remain |
room.disconnect() |
— | Disconnects. It is handled as if the connection dropped due to a network error, so it reconnects automatically |
room.action
| Function | Returns | Description |
|---|---|---|
send(message, style) |
true/false |
Sends a message. style is { bold, italic, underline, color } (all optional) |
slowRemaining() |
Milliseconds | Time left until you can send again under slow mode. 0 if you do not need to wait |
command(type, ...args) |
false if canceled in before.command, otherwise nothing |
Runs a command. See Commands below |
plugin(type, args) |
true/false |
Calls that channel's addParser callback, as if !type args had been typed in the chat box. For details, see Channel API and limits |
room.action.send('Hello');
room.action.send('Important!', { bold: true, color: '#e11d48' });
sendreturnsfalseif you are not connected, the message is empty, you must wait for slow mode, orbefore.sendblocked it.truemeans it was sent to the server; if the server rejects it, anerrorevent arrives.coloraccepts#rgb,#rrggbb,rgb(r, g, b), and color names.- For users who are not admins or moderators, the slow mode wait starts after sending.
Commands
The type in room.action.command(type, ...args) ignores case and _ (un_ignore → unignore). Before connecting, it does nothing. If you lack permission or the arguments are wrong, an error event arrives.
Common commands:
| Command | Arguments | Permission | Description |
|---|---|---|---|
whisper |
Nickname, text | — | Whisper |
call |
Nickname | — | Call |
ignore, unignore |
Nickname | — | Ignore and unignore (stored in this browser) |
report |
Nickname, reason | — | Report |
changeinfo |
{ nick: 'new nickname' } |
— | Change nickname |
password |
Password | — | Enter the entry password and rejoin |
chatlist |
Count (default 15, max 25) | — | Re-fetch past messages, plus whispers, calls, and invites addressed to you |
noticelist |
— | — | Fetch the chat room notices again (they arrive as the system event notice) |
individual |
— | — | Open your private channel in a new window |
invite |
Nickname | — | Invite that person to your private channel. Opens the private channel window first if it is not open |
popup |
— | — | Open this chat room in a new window (400×600) |
io |
true/false |
— | Turn join and leave notifications on or off. When off, you receive only the user count (user.count) |
login |
Admin password | — | Become an admin. Not available in member integration rooms |
info |
Nickname | Moderator (anyone for themselves) | User info |
notice |
Text | Moderator | Post a notice |
mute |
Nickname, minutes, reason | Moderator | Mute. Up to 30 days (43200 minutes) |
unmute |
Nickname | Moderator | Unmute |
ban |
Nickname, reason, duration (seconds) | Moderator | Ban. Permanent if the duration is empty or 0 |
ip |
Nickname | Moderator | Check IP |
freeze, unfreeze |
— | Moderator | Freeze and unfreeze the chat room |
clearlog |
— | Moderator | Clear the chat (without permission, clears only your own screen) |
op, deop |
Nickname | Admin | Grant and revoke moderator rights |
logout |
— | Admin | Give up admin permissions |
adminpage |
— | Admin | Open the admin page in a new window |
upload |
Callback | — | Legacy skins only. Opens the upload window and receives the result as callback(json) |
room.action.command('whisper', '홍길동', 'Do you have a moment to talk?');
room.action.command('changeinfo', { nick: 'NewNick' });
The server checks permissions again. Hiding a button in the UI does not by itself restrict a permission, and a command you lack permission for is rejected even if you send it.
room.setting
User settings stored only in this browser (localStorage). They share storage with the default skin's settings, so add a prefix to keys you create.
| Function | Description |
|---|---|
room.setting.get(key) |
Reads a value |
room.setting.set(key, value) |
Writes a value and saves immediately |
room.setting.save() |
Saves the current values |
room.setting.data |
The settings object itself |
room.setting.set('myScript.muted', true);
room.setting.get('myScript.muted'); // true
In browsers where storage is unavailable (such as private browsing), values may be lost on reload.
Still not sure how it works? Ask your question on the contact board.