Field guide · Cross-host import

How to import a Chub.ai card to SillyTavern, step by step.

You downloaded a PNG from Chub.ai, dropped it into SillyTavern, and something is off — the avatar is the placeholder silhouette, the lorebook never fires, only the first greeting shows up, or the import throws a spec_v2 error. None of that is mysterious once you know what is actually inside the file.

fol. i

TL;DR — Import in five steps

  1. On the Chub.ai card page, click Download to grab the PNG.
  2. Drop the PNG into your SillyTavern characters/ folder — path differs by deployment (see Step 2).
  3. Hit refresh in the SillyTavern UI (or reload the page) and pick the card from the list.
  4. Open the character, then sanity-check avatar + greetings + lorebook against the source.
  5. If something is missing, verify the embedded metadata with pngcheck -t card.png and re-export the card so the tEXt chunks are intact.
fol. ii

What actually lives inside a Chub.ai card

A character card from Chub is just a PNG with a JSON document smuggled into it. The PNG contains a tEXt chunk (keyword chara for V2, ccv3 for V3) whose value is Base64-encoded UTF-8 JSON. SillyTavern does not need to download “the card” from Chub in any special way — it reads the metadata embedded in the image itself. See: PNG tEXt chunk metadata explained.

V2 wraps the payload in an envelope:

{
  "spec": "chara_card_v2",
  "spec_version": "2.0",
  "data": { "name": "...", "description": "...", "character_book": { ... } }
}

V3 uses spec: "chara_card_v3" and adds fields like assets, nickname, group_only_greetings, and creator_notes_multilingual. Full V2 vs V3 breakdown.

When SillyTavern complains about spec_v2

This is the most-asked Chub-to-SillyTavern question on Reddit. The error wording shifts across SillyTavern releases — sometimes literally spec_v2, sometimes “Unsupported spec”, sometimes a silent fall-through to a V1 placeholder — but the underlying issue is almost always one of two things:

  1. The PNG was laundered in transit and the tEXt chunk is gone. Ancillary PNG chunks like tEXt can be dropped by anything that re-encodes the image: image editors saving via “Export As”, browsers round-tripping through canvas, social platforms running EXIF sanitisers, CDNs with image optimisation (Cloudflare Polish, Vercel /_next/image, Cloudinary auto-format). If you saved by right-clicking a Discord preview, screenshotting the Chub gallery, or copying out of a chat client, the metadata is gone and SillyTavern has nothing to parse. Verify with pngcheck -t card.png; if neither chara nor ccv3 shows up, that is the cause. Re-download via Chub’s Download button directly to disk.
  2. The card ships ccv3 only and your SillyTavern is older than V3 support. Some cards exported in the V3 era no longer include a chara fallback. SillyTavern builds prior to V3 landing have no idea what ccv3 is, fall back to looking for the V2 chunk, find none, and surface a spec-version-shaped error. Update SillyTavern, or re-export the card so it carries both a V2 and a V3 chunk for back-compat.

A distant third cause worth knowing about even though it is rare today: very old third-party export tools that wrote raw UTF-8 JSON straight into the tEXt value instead of Base64-encoded UTF-8. Modern Chub exports do not do this, but if you inherited a card from someone running an ancient pipeline, opening the PNG with exiftool or Python PIL.Image.open(...).text will show whether the value starts with { (raw JSON, broken) or Base64-looking ASCII (correct).

fol. iii

Step 1 — Download the card from Chub.ai

On the card’s detail page, the Download button gives you a PNG. Chub-exported cards typically ship a chara (V2) chunk for broad host compatibility, and may also carry a ccv3 (V3) chunk. Two things to do right here, before the file ever leaves Chub:

  • Save the PNG directly — not a screenshot or browser-cached preview. Right-click the Download button and save the link target. If your browser fetched an optimised variant for inline display, the inline copy may already be missing the tEXt chunk.
  • Keep the original. Make a copy and leave the original untouched. Some flows below involve re-exporting; you want a known-good source to compare against.
fol. iv

Step 2 — Drop the PNG into SillyTavern's character folder

SillyTavern reads character cards from a folder on disk. The exact path depends on how you deployed it.

DeploymentPath
Native (Windows / Mac / Linux)SillyTavern/data/default-user/characters/
Multi-user enabledSillyTavern/data/<your-user-handle>/characters/
Docker (official image)/home/node/app/data/default-user/characters/
Docker (volume-mounted)Whatever host path you bound to /home/node/app/data
WSL\\wsl$\<distro>\home\<user>\SillyTavern\data\default-user\characters\

A few gotchas worth flagging:

  • On multi-user installs the default-user folder is not used. Drop the file under your specific user handle or SillyTavern will not see it.
  • On Docker, copying to the host folder works only if you bind-mounted the data directory. If you ran docker run without -v, the characters/ folder lives inside the container and is wiped on docker rm.
  • File name matters less than you’d think — SillyTavern reads metadata from the tEXt chunk, not the filename. But avoid emoji or shell-unsafe characters; some Node FS operations on Windows still trip on them.

You can also import via the UI (Characters panel → import → pick file). For exactly one card that is fine; for batch imports the folder route is faster and skips a UI re-encode step.

fol. v

Step 3 — Refresh and verify in SillyTavern

Once the file is in the right folder:

  • If SillyTavern is running, hit the refresh icon at the top of the Characters panel. A full page reload (F5) also works and is more thorough.
  • If you imported through the UI, the card appears immediately.
  • Open the character. Confirm the portrait loads (not the default silhouette), the description block is populated, and the first greeting matches what you saw on Chub.

Quick field-level checklist before you start chatting:

  • Name — matches the Chub title
  • Description / personality / scenario — non-empty
  • First message — matches
  • Alternate greetings — count matches (Chub shows the number on the card page)
  • Lorebook — open Character Management → Advanced Definitions → Character Lore; the entries should be listed

If any row above is empty when it should not be, jump to Step 4.

fol. vi

Step 4 — The four common pitfalls

This is where most imports go sideways. Cross-reference what you see against the tavernai.cards compatibility matrix — a field-by-field map of which Tavern V2 / V3 fields survive each host’s export pipeline, including SillyTavern’s.

1. Avatar shows the default silhouette

The portrait you see is decorative — SillyTavern just renders the PNG as-is for the card thumbnail. If the PNG itself shows the right art in any image viewer but SillyTavern renders a silhouette, the card slot is loading without the file. More commonly: the PNG loads as an image but the tEXt chunk is gone, SillyTavern fails to parse it, and the slot displays as “broken card” with the placeholder.

Fix: Run pngcheck -t card.png. If you see chunks chara or ccv3 listed, the metadata is intact and the issue is elsewhere (permissions, wrong folder, multi-user mismatch — re-check Step 2). If no text chunks appear, the file was re-encoded somewhere upstream. Re-download from Chub directly via the Download button (not a preview, not a screenshot, not a CDN-mirrored copy).

2. Lorebook entries do not fire

Open Advanced Definitions → Character Lore. If entries are listed but never trigger in chat, two things to check:

  • case_sensitive is set to true on the entry, and your message uses a different case than the key. V2 lorebook entries have an optional case_sensitive flag; the spec default is false (case-insensitive), but the entry’s author can opt in. If your message says elara and the key is "Elara" with case_sensitive: true, the entry will never fire. Either flip the toggle off or add lowercase variants to the keys.
  • The entry’s enabled flag is false. Some entries ship disabled by default — the author may intend them as opt-in. Toggle them on.

Use the lorebook debugger to replay a sample transcript and see which entries actually matched, key by key.

3. Only one greeting, even though the card has several

V2 stores extras in alternate_greetings: string[]. SillyTavern’s UI surfaces them as a paginator on the greeting box. If you only see one, two possibilities: the card is V1 (no alternate_greetings field exists — check by inspecting the JSON; no spec field at the top level means V1), or a very old SillyTavern build is ignoring alternate_greetings. Update.

4. Filename or import errors out

Renames with emoji or full-width characters occasionally trip SillyTavern’s file walker on Windows. Strip the filename to ASCII — the card content is unaffected because the name shown in chat comes from the JSON name field, not the filename. If the error message mentions JSON parse failure rather than the filename, the tEXt value is malformed — proceed to Step 5.

fol. vii

Step 5 — When it still breaks: re-export with intact chunks

If the card is partially broken — tEXt chunk present but malformed, fields visibly missing, V3-only card needing a V2 fallback for an older host — the cleanest fix is to round-trip through a tool that reads, validates, and re-emits the PNG with spec-compliant chunks.

The minimum the tool needs to do:

  • Read both chara and ccv3 chunks; prefer ccv3 when both exist.
  • Validate the JSON against the V2 or V3 schema (catch the malformed-Base64, raw-UTF-8, and missing-spec cases).
  • Write back PNGs with both V2 and V3 chunks so the card loads on every modern host.
  • Preserve the image bytes untouched — re-encoding the pixels does not invalidate anything structurally but increases the chance of a downstream CDN re-stripping the chunks again.

A short menu of options:

  • A short Python script using Pillow (PIL.Image.open(...) reads .text, PngImagePlugin.PngInfo() writes a new chunk) — three or four lines for the common case.
  • exiftool can read chunk values for diagnosis (exiftool -PNG:chara card.png), but does not embed Base64-encoded tEXt cleanly for character cards — useful for inspection, not for re-export.
  • Community scripts on GitHub under search terms like tavern-card v2 png embed — pick one that has been touched in the last twelve months.

Whichever you use, verify the round trip with pngcheck -t card.png and confirm the chara (and ideally ccv3) keywords are listed before you re-import.

If you’d rather not script it: the tavernai.cards converter does exactly this round-trip in your browser — lint the card, validate the chunks, re-emit a V2 + V3 PNG, and audit the result before you re-import.

fol. viii

FAQ

How do I import a Chub.ai card to SillyTavern?

Download the card’s PNG from Chub.ai, drop it into your SillyTavern data/<user>/characters/ folder, then click refresh in the Characters panel. The card appears immediately because SillyTavern reads the JSON metadata embedded in the PNG’s tEXt chunk — no separate metadata file is needed. Path varies by deployment: native installs use the SillyTavern install directory; Docker uses an in-container path that should be bind-mounted to a host folder for persistence.

Does this work for V3 cards?

Yes, on modern SillyTavern builds. SillyTavern’s V3 support reads the ccv3 chunk and surfaces the V3-only fields. Older builds that pre-date V3 support fall back to the chara (V2) chunk if the card ships both, and silently ignore V3-only fields. The compatibility matrix tracks per-field SillyTavern support.

What if SillyTavern was updated and now my cards do not import?

Two common causes: the SillyTavern parser may have tightened and now rejects malformed JSON it previously accepted, or an upgrade-related file move left the cards in the wrong data/<user>/characters/ path. Run pngcheck -t card.png to confirm the chunk is still there, then cross-check the SillyTavern release notes for parser changes around your upgrade date.

Will a Chub.ai card work in RisuAI too?

Mostly. RisuAI reads V2 cards and the bulk of V3, with a few fields it interprets through its own UI conventions. The field-level differences are mapped in the compatibility matrix; pay attention to assets and creator_notes_multilingual in particular.

fol. ix

Where this matrix lives

The host-by-host, field-by-field compatibility matrix at /compat is updated as new SillyTavern, Chub, and RisuAI builds land. If you maintain a card library that has to live on more than one host, that page is the single source of truth for “will this field survive the trip.”

fol. x

Conclusion

Importing a Chub.ai card into SillyTavern is structurally simple — download the PNG, drop it into the characters folder, refresh. Every failure mode reduces to “the tEXt chunk is missing or malformed somewhere along the way.” The five-step flow above plus the four pitfalls cover essentially every variant of that question I see on r/SillyTavernAI.

If you maintain a roster that has to live on Chub, RisuAI, and SillyTavern at once, the tavernai.cards workbench is being built for exactly this — lint the card, round-trip both V2 and V3 chunks, and check it against the compatibility matrix before you ship. The waitlist is open at /#waitlist.

Chub.ai and SillyTavern are trademarks of their respective owners; this page is independent and not affiliated.

We’re opening the workbench in waves. If you maintain a card library that has to live on more than one host, put your name on the scroll.