Anonymous Login
A visitor can use the parts of your app that need an account, such as chat, private records or realtime, without signing up. anonymousLogin() signs the visitor in with a temporary anonymous account: no e-mail, no password, created by the one call.
The account lives while a page holds its session and is deleted 30 minutes after the visitor leaves.
Check the setting first
A project created from skapi.com starts with Anonymous Login on; a project created from bunnyquery.com, starts with it off. The owner turns it on or off in Project Settings. While it is off, anonymousLogin() fails with INVALID_REQUEST and Anonymous login is not enabled for this project. It works whether or not Allow Signup is on, so a project can close signups and still let visitors in anonymously.
Signing a visitor in
let user = await skapi.anonymousLogin();
console.log(user.anonymous); // trueanonymousLogin() resolves to the UserProfile of the new account, which carries anonymous: true, access group 1 and no e-mail. From then on the visitor is a logged-in user: skapi.user is set, the login listeners run, and every method that needs a login works, with the exceptions listed below.
Call it where your app decides a visitor needs an account, for example when the chat opens. It is safe to call on every page load:
- When the page already holds an anonymous session, it resolves to that account instead of creating another.
- When another user is logged in, it fails with
INVALID_REQUEST. Log that user out first if that is what you intend.
A page can tell whether anonymous login is on before any call: getConnectionInfo() returns it as conf.anonymous_login.
How long the account lives
The SDK keeps the account alive while a page holds its session: it sends a keep-alive every 10 minutes, once more when a page load restores the session from storage, and once more when the page comes back after a while (visible again, back online, or restored from the browser's back-forward cache). The account is deleted 30 minutes after the last keep-alive, which happens 30 to 40 minutes after the visitor closed the last page holding the session.
So:
- Reloading the page or opening it again within 30 minutes keeps the account and its data. The session is restored from the browser's storage, as for any login.
- A tab in the background on a computer keeps its account: browsers slow a background tab's timers, but not below the 10-minute beat.
- A phone is different: it freezes a page in the background completely, so no keep-alive goes out. A visitor who switches to another app for more than half an hour comes back to a deleted account, with the page still open. So does a laptop asleep for an hour.
- The SDK finds out as soon as the page comes back: the keep-alive it sends then learns that the account is gone and signs the page out (
skapi.userbecomesnulland the login listeners run withnull). A realtime connection that the server refuses to reopen for the account is checked the same way. The page can then callanonymousLogin()again for a new account; see Coming back to a deleted account.
To know before the page acts, await verifyAnonymousSession() on load. It waits for that first keep-alive and resolves with the profile, or with null once the account is gone, so the page can make a fresh account instead of failing its first request:
let user = await skapi.verifyAnonymousSession();
if (!user) {
user = await skapi.anonymousLogin();
}
await skapi.connectRealtime(handler);For a signed-in or a signed-out session it simply resolves with the current profile, so the same lines are safe on every page.
Coming back to a deleted account
A page that stays open (a call, a chat) needs one listener to survive the case above: when the session ends without the visitor logging out, make a new account and reconnect. The new account has a new user_id, so the others in a realtime group see the visitor leave and come back.
let leaving = false; // set it before your own logout(), so the listener leaves that one alone
skapi.onLogin = async (user) => {
if (user || leaving) return;
// the temporary account was deleted while the page was away
await skapi.closeRealtime();
await skapi.anonymousLogin(); // throws while the network is still down: try again a little later
await skapi.connectRealtime(handler);
await skapi.joinRealtime({ group: 'room-1' });
};logout() deletes an anonymous account at once. So does signup(), which logs out before it creates the new account. login() and openIdLogin() replace the session without a logout; the anonymous account they leave behind is deleted 30 minutes later.
When the account is deleted, everything it owns goes with it: its records, files, subscriptions and realtime state, as when any account is deleted.
What an anonymous account cannot do
A temporary account stays temporary. It cannot:
- edit its profile with
updateProfile(), - change its password with
changePassword(), or reset it withforgotPassword(), - verify an e-mail or a phone number with
verifyEmail()orverifyPhoneNumber(), - subscribe to newsletters,
- disable itself with
disableAccount()or be recovered.
Each of these fails with INVALID_REQUEST and a message starting with Anonymous accounts cannot. The refusal holds on the server as well, so a call made around the SDK is refused too.
Everything the feature is for stays allowed: records, files, realtime, subscriptions to other users, tickets, getProfile() and logout().
Telling anonymous users apart
- In your app:
skapi.user.anonymousistrueon an anonymous session and absent otherwise. - In
getUsers()results: an anonymous account's row carriesanonymous: true. - On the Users page of your project: an anonymous account shows Anonymous in the Email column with a crossed-out account icon. See Managing User Accounts.
An anonymous account counts as a user of your project while it exists, toward the plan's user limit and the month's active users. When the project is at its user limit, anonymousLogin() fails with INVALID_REQUEST and User limit exceeded., as a signup does.
Example: chat for visitors
async function openChat() {
if (!skapi.user) {
try {
await skapi.anonymousLogin();
}
catch (err) {
alert(err.message); // anonymous login is off, or the project is at its user limit
return;
}
}
showChatWindow();
}
skapi.onLogin = (user) => {
if (!user) {
// the anonymous account expired while the page was away: close the chat, let the visitor open it again
hideChatWindow();
}
};