Understanding and Reverse Engineering Character.AI
A deep dive of poking at character.ai's latest front-end redesign with the power of browser dev tools
Before the 2024 redesign of the site, when it was in beta; their infrastructure, back then and is still, ran entirely on Google Cloud Platform - and it isn’t a surprise if you figure out that since the founders were former engineers at Google.
Disclaimer
Just a heads up that I don't claim to work for character.ai at all! I'm just some lousy, masochist full-stack web dev who has a lot of free time on my hands. These are entirely my educated guesses and at any time, c.ai devs will change a thing or two in their front-end or their entire infrastructure, so take this information with a grain of salt.
The Redesign
Unsurprisingly, both the beta and the current version of the site were written in React; with the current one written on Next.js.
I find it surprising that it uses shadcn/ui as its choice for its UI library. I know this because during the development with MyFursona (now MyArtverse), Ozzy suggested using it for the project, and I was initially impressed since it’ll save time making a component library - but I was against it because I want it to have a “unique” look to the platform since it already uses Tailwind and to work on tandem with Headless UI... but I digress.
Overall, I consider the new version of the character.ai site to be an upgrade in terms of UI compared to the old one, even if it has that “Vercel” look and feel.
Amidst the ongoing transition to the new site, it still had the domain of beta.character.ai but in the preceding months, they changed the subdomain to old.character.ai; as of currently writing this blog, the old site has a lot of broken CSS and is barely usable - at least for me, it seems to work as intended for everyone else for some reason.
About Character.AI’s APIs
character.ai does have an API, you’ll need to contact them to get access for a specific use case and it isn't publicly available for everyone. Thankfully, people have built non-official API wrappers such as this Python package but was unmaintained for 2 years now and I wouldn’t guarantee it will work with the recent redesign.
So, if you’re trying to build something on top of character.ai, you have no other choice but to use a tool like Selenium WebDriver to programmatically traverse it through the website.
Wapplyzer analysis
I first visited the website in December last year and had Waaplyzer installed, a browser extension that detects technologies such as JavaScript frameworks, libraries, CSS libraries, and more.
In their beta or "old" version of their site, one of the technologies they used categorized under IaaS or Infrastructure as a Service was Google Cloud Platform. I'm still unsure if they use Sass or anything, they use Bootstrap as the UI framework, but they use Tailwind on the current site.
Looking At Character.AI Under The Hood
Using browser dev tools, I noticed three subdomains under *.character.ai; neo.character.ai, events.character.ai, and plus.character.ai:
neo.character.ai is responsible for pinging the servers, handling ratings and feedback from AI’s response, retrieving previous chat sessions, and most importantly, establishing a WebSocket connection whenever you initiate a chatroom so it’ll receive messages back and forth. If you have a lengthy chat session, it’ll retrieve the first 50 messages to where you left off through a normal GET request instead.
plus.character.ai is responsible for user authentication, storing and updating user settings (possibly even the subscription too, hence the “plus” in the subdomain), and handling user-created personas; creating, and overriding a persona on a current chat session is all sent through a POST request.
events.character.ai is just purely analytics stuff. It sends a POST request of whatever the end user is doing. Or it could be possible to notify the AI that the persona has changed, but I’m not entirely sure.
The new AI voice feature
character.ai also has a voice feature that uses Livekit, which is also what OpenAI utilizes for ChatGPT mobile apps. Digging deeper, when turned on, it sends a GET request from caimm-7f849j8w.livekit.cloud and establishes its separate WebSocket connection too. It’ll disconnect itself after several minutes of inactivity, most likely to save on server resources. It terminates on status codes 1005 (No Status Received), and 1000 (Normal Closure) if you decide to turn it off yourself.
And just recently, as of writing this blog — a few days ago, they’ve added a feature to play back the generated messages without enabling the voice feature.
However, there’s a catch: if you edit the AI’s messages and try to play it back - you’ll get an error. But why’s that? Upon inspecting its request, it received a status code of 412 Precondition Failed. It turns out that the text that the AI-generated from the server doesn’t match what you edited, hence returning a vague error on the consumer’s end.
But some of you are like, “why couldn’t they regenerate the edited message then?” I believe running something like this at scale, especially to a lot of people, isn’t exactly easy to operate - let alone with AI text generation being so expensive to maintain.