# PyCharacterAI
> An asynchronous Python api wrapper for [Character AI](https://character.ai/) using [curl-cffi](https://github.com/yifeikong/curl_cffi).
> [!WARNING]
> This is an unofficial library made by an enthusiast who has no relation to the CharacterAI development team. CharacterAI has no official api and all breakpoints were found manually using reverse proxy. The author is not responsible for possible consequences of using this library.
>
> The library is under constant development, trying to match the functionality of the website. Anything that isn't described in the documentation may be changed or removed without backward compatibility!
---
📚 [Documentation](https://github.com/Xtr4F/PyCharacterAI/blob/main/docs/welcome.md).
---
**TO-DO**:
- [x] Exceptions.
- [ ] Logging?
- [ ] Finish the docs.
---
\
If you have any questions, problems, suggestions, please open an issue or contact me:
[![Tag](https://img.shields.io/badge/telegram-dm-black?style=flat&logo=Telegram)](https://t.me/XtraF)
---
## Getting started
First, you need to install the library:
```bash
pip install git+https://github.com/Xtr4F/PyCharacterAI
```
---
\
Import the `Client` class from the library and create a new instance of it:
```Python
from PyCharacterAI import Client
```
```Python
client = Client()
```
Then you need to authenticate `client` using `token`:
```Python
await client.authenticate("TOKEN")
```
> if you want to be able to upload your avatar you also need to specify `web_next_auth` token as an additional argument (only this way for now, this may change in the future):
> ```Python
> await client.authenticate("TOKEN", web_next_auth="WEB_NEXT_AUTH")
> ```
\
Or you can just call `get_client()` method:
```Python
from PyCharacterAI import get_client
client = await get_client(token="TOKEN", web_next_auth="WEB_NEXT_AUTH")
```
After authentication, we can use all available library methods.
---
## About tokens and how to get them:
> ⚠️ WARNING, DO NOT SHARE THESE TOKENS WITH ANYONE! Anyone with your tokens has full access to your account!
This library uses two types of tokens: a common `token` and `web_next_auth`. The first one is required for almost all methods here and the second one only and only for `upload_avatar()` method (may change in the future).
### Instructions for getting a `token`:
1. Open the Character.AI website in your browser
2. Open the `developer tools` (`F12`, `Ctrl+Shift+I`, or `Cmd+J`)
3. Go to the `Nerwork` tab
4. Interact with website in some way, for example, go to your profile and look for `Authorization` in the request header
5. Copy the value after `Token`
> For example, token in `https://plus.character.ai/chat/user/public/following/` request headers:
> ![img](https://github.com/Xtr4F/PyCharacterAI/blob/main/assets/token.png)
### Instructions for getting a `web_next_auth` token:
1. Open the Character.AI website in your browser
2. Open the `developer tools` (`F12`, `Ctrl+Shift+I`, or `Cmd+J`)
3. Go to the `Storage` section and click on `Cookies`
4. Look for the `web-next-auth` key
5. Copy its value
> ![img](https://github.com/Xtr4F/PyCharacterAI/blob/main/assets/web_next_auth.png)
---
## Examples
> Here are just some examples of the library's features. If you want to know about all `methods` and `types` with explanations, go to [methods](https://github.com/Xtr4F/PyCharacterAI/blob/main/docs/api_reference/methods.md) and [types](https://github.com/Xtr4F/PyCharacterAI/blob/main/docs/api_reference/types.md) documentation sections.
### Simple chatting example:
```Python
import asyncio
from PyCharacterAI import get_client
from PyCharacterAI.exceptions import SessionClosedError
token = "TOKEN"
character_id = "ID"
async def main():
client = await get_client(token=token)
me = await client.account.fetch_me()
print(f"Authenticated as @{me.username}")
chat, greeting_message = await client.chat.create_chat(character_id)
print(f"{greeting_message.author_name}: {greeting_message.get_primary_candidate().text}")
try:
while True:
# NOTE: input() is blocking function!
message = input(f"[{me.name}]: ")
answer = await client.chat.send_message(character_id, chat.chat_id, message)
print(f"[{answer.author_name}]: {answer.get_primary_candidate().text}")
except SessionClosedError:
print("session closed. Bye!")
finally:
# Don't forget to explicitly close the session
await client.close_session()
asyncio.run(main())
```
---
A more advanced example. You can use so-called streaming to receive a message in parts, as is done on a website, instead of waiting for it to be completely generated:
```Python
import asyncio
from PyCharacterAI import get_client
from PyCharacterAI.exceptions import SessionClosedError
token = "TOKEN"
character_id = "ID"
async def main():
client = await get_client(token=token)
me = await client.account.fetch_me()
print(f'Authenticated as @{me.username}')
chat, greeting_message = await client.chat.create_chat(character_id)
print(f"[{greeting_message.author_name}]: {greeting_message.get_primary_candidate().text}")
try:
while True:
# NOTE: input() is blocking function!
message = input(f"[{me.name}]: ")
answer = await client.chat.send_message(character_id, chat.chat_id, message, streaming=True)
printed_length = 0
async for message in answer:
if printed_length == 0:
print(f"[{message.author_name}]: ", end="")
text = message.get_primary_candidate().text
print(text[printed_length:], end="")
printed_length = len(text)
print("\n")
except SessionClosedError:
print("session closed. Bye!")
finally:
# Don't forget to explicitly close the session
await client.close_session()
asyncio.run(main())
```
---
### Working with images:
```Python
# We can generate images from a prompt
# (It will return list of urls)
images = await client.utils.generate_image("prompt")
```
---
```Python
# We can upload an image to use it as an
# avatar for character/persona/profile
# NOTE: This method requires the specified web_next_auth token
avatar_file = "path to file or url"
avatar = await client.utils.upload_avatar(avatar_file)
```
---
### Working with voices:
```Python
# We can search for voices
voices = await client.utils.search_voices("name")
```
---
```Python
# We can upload the audio as a voice
voice_file = "path to file or url"
voice = await client.utils.upload_voice(voice_file, "voice name")
```
---
```Python
# We can set and unset a voice for character
await client.account.set_voice("character_id", "voice_id")
await client.account.unset_voice("character_id")
```
---
```Python
# And we can use voice to generate speech from the character's messages
speech = await client.utils.generate_speech("chat_id", "turn_id", "candidate_id", "voice_id")
# It will return bytes, so we can use it for example like this:
filepath = "voice.mp3"
with open(filepath, 'wb') as f:
f.write(speech)
```
```Python
# or we can get just the url.
speech_url = await client.utils.generate_speech("chat_id", "turn_id", "candidate_id",
"voice_id", return_url=True)
```
---
## Special Thanks
- [node_characterai](https://github.com/realcoloride/node_characterai) by @realcoloride - for being the backbone of the project in the past.
- [CharacterAI](https://github.com/kramcat/CharacterAI) by @kramcat - for inspiring me.
Raw data
{
"_id": null,
"home_page": null,
"name": "PyCharacterAI",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "XtraF <igoromarov15@gmail.com>",
"keywords": "ai, api, asyncio, cai, character, characterai, wrapper",
"author": null,
"author_email": "XtraF <igoromarov15@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/53/1b/e1ec529a25f26b0313c676e6649d893974e633ed7d60c235233868cdc49c/pycharacterai-2.2.2.tar.gz",
"platform": null,
"description": "# PyCharacterAI\n> An asynchronous Python api wrapper for [Character AI](https://character.ai/) using [curl-cffi](https://github.com/yifeikong/curl_cffi).\n\n> [!WARNING]\n> This is an unofficial library made by an enthusiast who has no relation to the CharacterAI development team. CharacterAI has no official api and all breakpoints were found manually using reverse proxy. The author is not responsible for possible consequences of using this library. \n> \n> The library is under constant development, trying to match the functionality of the website. Anything that isn't described in the documentation may be changed or removed without backward compatibility!\n\n\n\n---\n\ud83d\udcda [Documentation](https://github.com/Xtr4F/PyCharacterAI/blob/main/docs/welcome.md).\n\n\n---\n**TO-DO**:\n- [x] Exceptions.\n- [ ] Logging?\n- [ ] Finish the docs.\n\n---\n\\\nIf you have any questions, problems, suggestions, please open an issue or contact me:\n\n[![Tag](https://img.shields.io/badge/telegram-dm-black?style=flat&logo=Telegram)](https://t.me/XtraF)\n\n\n\n---\n\n## Getting started\n\nFirst, you need to install the library:\n```bash\npip install git+https://github.com/Xtr4F/PyCharacterAI\n```\n\n---\n\\\nImport the `Client` class from the library and create a new instance of it:\n```Python\nfrom PyCharacterAI import Client\n```\n\n```Python\nclient = Client()\n```\n\nThen you need to authenticate `client` using `token`:\n```Python\nawait client.authenticate(\"TOKEN\")\n```\n\n> if you want to be able to upload your avatar you also need to specify `web_next_auth` token as an additional argument (only this way for now, this may change in the future):\n> ```Python\n> await client.authenticate(\"TOKEN\", web_next_auth=\"WEB_NEXT_AUTH\")\n> ```\n\n\\\nOr you can just call `get_client()` method:\n```Python\nfrom PyCharacterAI import get_client\n\nclient = await get_client(token=\"TOKEN\", web_next_auth=\"WEB_NEXT_AUTH\")\n```\n\nAfter authentication, we can use all available library methods.\n\n---\n## About tokens and how to get them:\n> \u26a0\ufe0f WARNING, DO NOT SHARE THESE TOKENS WITH ANYONE! Anyone with your tokens has full access to your account! \n\nThis library uses two types of tokens: a common `token` and `web_next_auth`. The first one is required for almost all methods here and the second one only and only for `upload_avatar()` method (may change in the future).\n\n### Instructions for getting a `token`:\n1. Open the Character.AI website in your browser\n2. Open the `developer tools` (`F12`, `Ctrl+Shift+I`, or `Cmd+J`)\n3. Go to the `Nerwork` tab\n4. Interact with website in some way, for example, go to your profile and look for `Authorization` in the request header\n5. Copy the value after `Token`\n> For example, token in `https://plus.character.ai/chat/user/public/following/` request headers:\n> ![img](https://github.com/Xtr4F/PyCharacterAI/blob/main/assets/token.png)\n\n### Instructions for getting a `web_next_auth` token:\n1. Open the Character.AI website in your browser\n2. Open the `developer tools` (`F12`, `Ctrl+Shift+I`, or `Cmd+J`)\n3. Go to the `Storage` section and click on `Cookies`\n4. Look for the `web-next-auth` key\n5. Copy its value\n> ![img](https://github.com/Xtr4F/PyCharacterAI/blob/main/assets/web_next_auth.png)\n\n\n---\n\n## Examples\n> Here are just some examples of the library's features. If you want to know about all `methods` and `types` with explanations, go to [methods](https://github.com/Xtr4F/PyCharacterAI/blob/main/docs/api_reference/methods.md) and [types](https://github.com/Xtr4F/PyCharacterAI/blob/main/docs/api_reference/types.md) documentation sections.\n### Simple chatting example:\n```Python\nimport asyncio\n\nfrom PyCharacterAI import get_client\nfrom PyCharacterAI.exceptions import SessionClosedError\n\ntoken = \"TOKEN\"\ncharacter_id = \"ID\"\n\n\nasync def main():\n client = await get_client(token=token)\n\n me = await client.account.fetch_me()\n print(f\"Authenticated as @{me.username}\")\n\n chat, greeting_message = await client.chat.create_chat(character_id)\n\n print(f\"{greeting_message.author_name}: {greeting_message.get_primary_candidate().text}\")\n\n try:\n while True:\n # NOTE: input() is blocking function!\n message = input(f\"[{me.name}]: \")\n\n answer = await client.chat.send_message(character_id, chat.chat_id, message)\n print(f\"[{answer.author_name}]: {answer.get_primary_candidate().text}\")\n\n except SessionClosedError:\n print(\"session closed. Bye!\")\n\n finally:\n # Don't forget to explicitly close the session\n await client.close_session()\n\nasyncio.run(main())\n```\n\n---\n\nA more advanced example. You can use so-called streaming to receive a message in parts, as is done on a website, instead of waiting for it to be completely generated:\n```Python\nimport asyncio\n\nfrom PyCharacterAI import get_client\nfrom PyCharacterAI.exceptions import SessionClosedError\n\ntoken = \"TOKEN\"\ncharacter_id = \"ID\"\n\n\nasync def main():\n client = await get_client(token=token)\n\n me = await client.account.fetch_me()\n print(f'Authenticated as @{me.username}')\n\n chat, greeting_message = await client.chat.create_chat(character_id)\n\n print(f\"[{greeting_message.author_name}]: {greeting_message.get_primary_candidate().text}\")\n\n try:\n while True:\n # NOTE: input() is blocking function!\n message = input(f\"[{me.name}]: \")\n\n answer = await client.chat.send_message(character_id, chat.chat_id, message, streaming=True)\n\n printed_length = 0\n async for message in answer:\n if printed_length == 0:\n print(f\"[{message.author_name}]: \", end=\"\")\n\n text = message.get_primary_candidate().text\n print(text[printed_length:], end=\"\")\n\n printed_length = len(text)\n print(\"\\n\")\n\n except SessionClosedError:\n print(\"session closed. Bye!\")\n\n finally:\n # Don't forget to explicitly close the session\n await client.close_session()\n\nasyncio.run(main())\n```\n\n---\n\n### Working with images:\n```Python\n# We can generate images from a prompt\n# (It will return list of urls)\nimages = await client.utils.generate_image(\"prompt\")\n```\n---\n```Python\n# We can upload an image to use it as an \n# avatar for character/persona/profile\n\n# NOTE: This method requires the specified web_next_auth token\navatar_file = \"path to file or url\"\navatar = await client.utils.upload_avatar(avatar_file)\n```\n\n---\n\n### Working with voices:\n```Python\n# We can search for voices\nvoices = await client.utils.search_voices(\"name\")\n```\n---\n```Python\n# We can upload the audio as a voice\nvoice_file = \"path to file or url\"\nvoice = await client.utils.upload_voice(voice_file, \"voice name\")\n```\n---\n```Python\n# We can set and unset a voice for character \nawait client.account.set_voice(\"character_id\", \"voice_id\")\nawait client.account.unset_voice(\"character_id\")\n```\n---\n```Python\n# And we can use voice to generate speech from the character's messages\nspeech = await client.utils.generate_speech(\"chat_id\", \"turn_id\", \"candidate_id\", \"voice_id\")\n\n# It will return bytes, so we can use it for example like this:\nfilepath = \"voice.mp3\"\n\nwith open(filepath, 'wb') as f:\n f.write(speech)\n```\n```Python\n# or we can get just the url.\nspeech_url = await client.utils.generate_speech(\"chat_id\", \"turn_id\", \"candidate_id\", \n \"voice_id\", return_url=True)\n\n```\n---\n## Special Thanks\n- [node_characterai](https://github.com/realcoloride/node_characterai) by @realcoloride - for being the backbone of the project in the past.\n\n\n- [CharacterAI](https://github.com/kramcat/CharacterAI) by @kramcat - for inspiring me.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
"bugtrack_url": null,
"license": null,
"summary": "An unofficial asynchronous api wrapper for Character AI.",
"version": "2.2.2",
"project_urls": {
"Documentation": "https://github.com/Xtr4F/PyCharacterAI/blob/main/docs/welcome.md",
"Homepage": "https://github.com/Xtr4F/PyCharacterAI",
"Issues": "https://github.com/Xtr4F/PyCharacterAI/issues",
"Repository": "https://github.com/Xtr4F/PyCharacterAI.git"
},
"split_keywords": [
"ai",
" api",
" asyncio",
" cai",
" character",
" characterai",
" wrapper"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "835578b69fe10c7c04e66b337a1a6684d094940165d69c9c9ca6a331897d93ba",
"md5": "670b47c425153c580f0716669aa95a4e",
"sha256": "433425c50b1044637f3f5dc83a1c0162fd69ff1f428b4aa44a27afa51a6d3ee7"
},
"downloads": -1,
"filename": "pycharacterai-2.2.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "670b47c425153c580f0716669aa95a4e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 24811,
"upload_time": "2025-01-16T12:09:48",
"upload_time_iso_8601": "2025-01-16T12:09:48.723802Z",
"url": "https://files.pythonhosted.org/packages/83/55/78b69fe10c7c04e66b337a1a6684d094940165d69c9c9ca6a331897d93ba/pycharacterai-2.2.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "531be1ec529a25f26b0313c676e6649d893974e633ed7d60c235233868cdc49c",
"md5": "757feb2d291d8299d06bb6e9e7925578",
"sha256": "eb4fcda077ddefb8c62f41dfa7866db503b046e19fede1b56397e7a5eb0c15b3"
},
"downloads": -1,
"filename": "pycharacterai-2.2.2.tar.gz",
"has_sig": false,
"md5_digest": "757feb2d291d8299d06bb6e9e7925578",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 265658,
"upload_time": "2025-01-16T12:09:52",
"upload_time_iso_8601": "2025-01-16T12:09:52.758171Z",
"url": "https://files.pythonhosted.org/packages/53/1b/e1ec529a25f26b0313c676e6649d893974e633ed7d60c235233868cdc49c/pycharacterai-2.2.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-16 12:09:52",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Xtr4F",
"github_project": "PyCharacterAI",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "pycharacterai"
}