A Python script that exports your Nomi.ai conversation history to self-contained HTML files — one chat transcript per Nomi, plus an optional mind map page and media gallery. No external dependencies beyond the Python standard library (one optional package for richer mind map rendering).
Find this script useful? Consider making a donation through PayPal at toddkarwoski.com/buymeacoffee
Individual screenshots (desktop + mobile)
| Desktop | Mobile | |
|---|---|---|
| Landing page | ![]() |
![]() |
| Chat transcript | ![]() |
![]() |
| Mind map | ![]() |
![]() |
| Media gallery | ![]() |
![]() |
- Full chat transcript — every message, paginated from the beginning of history
- Voice call transcripts — inline in the chat, visually distinct from text messages
- Mind map archive — Lore, Topics, and Goals sections with dossier details rendered from markdown
- Media gallery — selfies, character images, and videos all in one page
- Selfies and character images downloaded as
.webpfiles with a click-to-enlarge lightbox - Videos downloaded as
.mp4with a preview thumbnail and play button; clicking autoplays in a lightbox - Videos are excluded from the chat transcript and appear only in the media gallery
- Selfies and character images downloaded as
- Incremental updates — re-running the script only downloads new messages, calls, and media; existing history is preserved in a JSON cache
- Local timestamps — all message times are converted to your browser's local timezone automatically
- Cross-page navigation — chat, mind map, and media pages all link to each other
- Landing page —
index.htmlshows all archived Nomis as cards with their character image as background, sorted by first chat date - No external server needed — HTML files open directly in any browser
- Python 3.9 or later
- A Nomi.ai account with at least one Nomi
Optional (enables markdown rendering in mind map dossiers):
pip install markdownWithout this package the script still works; dossier text is shown as plain pre-formatted text instead.
You need up to three values depending on which features you want.
- Open beta.nomi.ai and sign in
- Click your profile avatar → Integration
- Copy the API key shown there
The session token unlocks the richer internal API, which is needed for voice call transcripts, mind map data, and media downloads.
- Open beta.nomi.ai in Chrome and sign in
- Press F12 to open DevTools
- Go to the Application tab
- In the left sidebar expand Storage → Cookies → https://beta.nomi.ai
- Find the cookie named
__Secure-next-auth.session-token - Copy its Value (a long string)
Note: Session tokens expire when you sign out. If the script starts returning auth errors, grab a fresh token using the steps above.
- Open beta.nomi.ai and click into any conversation
- Look at the URL — it will look like
beta.nomi.ai/nomis/1234567890 - The number at the end is your Nomi's numeric ID
The script stores this in its cache after the first successful run, so you only need to provide it once per Nomi.
Multiple Nomis: If you have more than one Nomi, run the script once per Nomi on the first run, each time passing that Nomi's --nomi-id. After that, all Nomis are handled automatically in a single run.
python3 nomivault.py --key YOUR_API_KEYDownloads text chat history for every Nomi on your account. Voice transcripts, mind map, and media gallery are not included.
python3 nomivault.py --key YOUR_API_KEY --token YOUR_SESSION_TOKEN --nomi-id 1234567890On every subsequent run the --nomi-id argument can be omitted because the ID is saved in the cache.
python3 nomivault.py --key YOUR_API_KEY --token YOUR_SESSION_TOKENOnly new messages and voice calls since the last run are downloaded. Existing history is merged from the local cache.
python3 nomivault.py --key YOUR_API_KEY --token YOUR_SESSION_TOKEN --fullIgnores the local cache and fetches the entire history again.
python3 nomivault.py --key YOUR_API_KEY --token YOUR_SESSION_TOKEN --output ~/Documents/nomiThe directory is created automatically if it does not exist.
| Argument | Required | Description |
|---|---|---|
--key KEY |
Yes | Your Nomi.ai API key (Profile → Integration) |
--token TOKEN |
No* | __Secure-next-auth.session-token cookie value from beta.nomi.ai. Required for voice transcripts, mind map, and media gallery. |
--nomi-id ID |
No* | Numeric Nomi ID from the beta.nomi.ai URL (e.g. 1234567890). Required on the first --token run per Nomi; cached afterwards. |
--output DIR |
No | Directory to write all output files. Defaults to an output/ folder next to nomivault.py. |
--full |
No | Ignore the local cache and re-download the entire conversation history. |
--messages-url PATTERN |
No | Override the message endpoint pattern for the public API (no-token mode only), e.g. "/v1/nomis/{uuid}/chats". |
--silent |
No | Suppress all terminal output. Run output is still captured and included in the error email if SMTP is configured. |
--smtp-config FILE |
No | Path to an INI file with SMTP settings for error-notification emails. Defaults to smtp.ini next to nomivault.py when that file exists. |
The script writes files to the output directory:
| File | Description |
|---|---|
index.html |
Landing page — card grid linking to every archived Nomi |
<NomiName>.html |
Full chat transcript with voice call transcripts inline |
<NomiName>-mind-map.html |
Mind map with Lore, Topics, and Goals sections |
<NomiName>-media.html |
Media gallery with selfies, character images, and videos |
<NomiName>.json |
Cache file used for incremental updates — do not delete |
media/<NomiName>/*.webp |
Downloaded selfie images, character images, and video preview thumbnails |
media/<NomiName>/*.mp4 |
Downloaded video files |
Open any .html file directly in Chrome or Edge. No web server is needed.
Each mind map entry can have a detailed dossier. These are stored as markdown in the Nomi.ai API and rendered to HTML in the output. Install the markdown package for full rendering:
pip install markdownWithout it, dossier text is shown as plain formatted text and all other mind map features still work normally.
Running the script regularly adds new messages without re-downloading old ones. A simple approach on Windows with WSL:
# Add to a scheduled task or run manually whenever you want an update
python3 /path/to/nomivault.py --key YOUR_API_KEY --token YOUR_SESSION_TOKENThe script is designed to run unattended. If anything goes wrong it exits with a non-zero code and can send you an email with the full run output so you can see exactly what failed.
Copy smtp.ini.example to smtp.ini (in the same folder as nomivault.py) and fill in your SMTP credentials:
cp smtp.ini.example smtp.ini
nano smtp.ini # or open in any text editorsmtp.ini is excluded from git so your credentials are never committed.
Gmail tip: use an App Password rather than your account password. Generate one at Google Account → Security → App passwords.
Pass --silent to suppress all terminal output. The run output is still captured internally and included in any error email:
python3 nomivault.py --key YOUR_API_KEY --token YOUR_SESSION_TOKEN --silentLinux / macOS cron — edit with crontab -e:
# Run every day at 3 AM
0 3 * * * /usr/bin/python3 /path/to/nomivault.py --key YOUR_KEY --token YOUR_TOKEN --silentWindows Task Scheduler — create a basic task that runs:
Program: python.exe
Arguments: C:\path\to\nomivault.py --key YOUR_KEY --token YOUR_TOKEN --silent
- The script exits with code
1on any unrecoverable error. - If
smtp.iniis present (or--smtp-config FILEis passed), a notification email is sent to the address in thetofield. The email subject includes your hostname and the body contains the complete run output. - If no SMTP config is found, the non-zero exit code alone signals the failure to the scheduler.
Your session token has expired. Grab a fresh one from DevTools (see Getting Your Credentials).
The numeric Nomi ID is wrong or missing. Check the URL on beta.nomi.ai and pass the correct value with --nomi-id.
The script needs the numeric ID on the very first run for each Nomi. Find it in the URL on beta.nomi.ai (beta.nomi.ai/nomis/XXXXXXX) and run once with --nomi-id XXXXXXX. The ID is cached automatically and subsequent runs need no flag.
These require --token. Make sure the session token is current and that --nomi-id was provided on the first run.
If the script detects that the API cursor is not advancing it stops automatically to avoid an infinite loop. Run with --full to force a complete re-download.
Nomi.ai occasionally updates their internal API version string. If you see unexpected 400 errors on the beta API, open DevTools on beta.nomi.ai, look at any network request to beta.nomi.ai/api/..., and find the av= query parameter. Update the BETA_AV constant near the top of nomivault.py to match.
The output/ directory is excluded from this repository via .gitignore. Your conversation data, HTML exports, and JSON cache files are never committed to git. Keep that folder private.








