npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

simple_node_characterai

v1.1.2

Published

Simple Node.js library for interacting with Character.AI via HTTP and WebSocket with typescript

Readme

THIS PACKAGE HEAVILY INSPIRED BY node_characterai PACKAGE.

Character AI (Node) Package

Simple Node.js library for interacting with Character.AI via HTTP and WebSocket with typescript. It provides simple primitives to authenticate, create chats, send messages, and fetch chat turns. Perfect usage for route handlers in Node.js applications that need interactions with Character.AI in custom interface.

Features

  • Authenticate with a session token and initialize a WebSocket
  • Create one-on-one chats with characters
  • Send messages and await final replies
  • Fetch chat turns (messages) with pagination
  • Minimal, typed API with clear data models

Installation

npm install simple_node_characterai

Quick Start

import { authenticate, createNewConversation, sendMessage, getMessages, getProfile } from 'simple_node_characterai';

(async () => {
  // 1) Authenticate with your session token (string without "Token " prefix is fine)
  await authenticate('YOUR_SESSION_TOKEN');

  // 2) Access the authenticated user profile
  const profile = getProfile();
  console.log('Logged in as:', profile.user.username);

  // 3) Create a new chat with a character
  const characterId = 'CHARACTER_ID';
  const addTurn = await createNewConversation(characterId);
  const chatId = addTurn.turn.turn_key.chat_id;

  // 4) Send a message and wait for the final candidate
  const response = await sendMessage('Hello!', characterId, chatId);
  console.log(response.turn.candidates[0].raw_content);

  // 5) Fetch latest turns (up to 50)
  const turns = await getMessages(chatId);
  console.log('Turns count:', turns.length);
})();

Example with Hono Route Handler

import { Hono } from 'hono'
import { authenticate, createNewConversation, sendMessage, getMessages, getProfile } from 'simple_node_characterai';

const app = new Hono();

(async () => {
  await authenticate(process.env.CHARACTERAI_TOKEN!);
})();

// Creates a new one-on-one conversation
// Body: { characterId: string } -> Response: { chatId: string }
app.post('/conversations', async (c) => {
  try {
    const body = await c.req.json();
    const characterId = body?.characterId;
    if (!characterId) return c.json({ error: 'characterId is required' }, 400);
    const addTurn = await createNewConversation(characterId);
    const chatId = addTurn.turn.turn_key.chat_id;
    return c.json({ chatId });
  } catch (e) {
    return c.json({ error: 'failed to create conversation' }, 500);
  }
});

// Sends a message to a conversation and returns the final content
// Body: { message: string, characterId: string, chatId: string }
// Make sure to store the characterId and chatId somewhere, like Database
// The messages field can be get in response.turn.candidates[0].raw_content
app.post('/messages', async (c) => {
  try {
    const body = await c.req.json();
    const message = body?.message;
    const characterId = body?.characterId;
    const chatId = body?.chatId;
    if (!message || !characterId || !chatId) {
      return c.json({ error: 'message, characterId, and chatId are required' }, 400);
    }
    const response = await sendMessage(message, characterId, chatId);
    const final = response.turn.candidates?.[0];
    return c.json({
      turn: response.turn,
      content: final?.raw_content ?? null
    });
  } catch (e) {
    return c.json({ error: 'failed to send message' }, 500);
  }
});

// Fetches up to 50 turns for the given chatId
// Optional query: ?token=NEXT_TOKEN for pagination
// Token will be available in meta field of response if there's more turns to fetch.
app.get('/messages/:chatId', async (c) => {
  try {
    const chatId = c.req.param('chatId');
    const token = c.req.query('token') ?? undefined;
    const messages = await getMessages(chatId, token);
    return c.json({ turns: messages.turns, token: messages.meta.next_token });
  } catch (e) {
    return c.json({ error: 'failed to fetch messages' }, 500);
  }
});

export default app

Find Authorization Token

  1. Logged in to character.ai
  2. Make sure to select any character first
  3. Open the developer tools F12, FN + F12, CTRL + SHIFT + I
  4. Go to Application tab
  5. Navigate to Cookies section, and select https://character.ai cookies
  6. Look up for HTTP_AUTHORIZATION token with string that starts with Token
  7. If token doesn't present, refresh the page and see the token again
  8. Copy the value

Sometimes the token will show up for a minutes and dissapear.

Find Character ID and Chat ID

Logged in to character.ai, and select a character you want to chat, then look up at URL, the URL contains the Character and Chat ID with following detail:

https://character.ai/chat/{characterId}?hist={chatId}

API Reference

Auth

authenticate(sessionToken: string): Promise

  • Authenticates the user, validates the token, loads the profile, and opens the WebSocket.
  • Accepts either raw token or "Token XXX" format.

getProfile(): Profile

  • Returns the in-memory authenticated user profile.

Chat

createNewConversation(characterId: string): Promise

  • Creates a new one-on-one chat with the specified character and resolves when the greeting turn arrives.
  • Returns metadata and the initial turn.

sendMessage(message: string, characterId: string, chatId: string): Promise

  • Sends a user message to an existing chat.
  • Resolves when the model returns a final candidate for the turn.

getMessages(chatId: string, token?: string): Promise<Turn[]>

  • Retrieves up to 50 turns for the given chat.
  • If a token is provided, fetches the next page of results using next_token.

Notes

  • This package is intended for personal use.
  • Avoid logging tokens, cookies, or PII; keep sensitive information in memory.
  • When building client-side applications, follow CORS restrictions; this package is designed for server-side Node usage.

Development

Still in development but ready to use for basic chatting usage, more feature will be added in the future.