The avatar file

The self-contained .imx file every bitHuman avatar ships in — one container for Essence 1, Essence 2 and Expression 2 identities — where it comes from, how it's addressed by agent code, and how to inspect it.

What an .imx is

An .imx file is the container a bitHuman avatar ships in: one self-contained file of identity weights, textures and a manifest (model version, ABI, license) that an engine reads to animate one specific face. Every model that renders on your own hardware uses it — a first-generation Essence 1 identity, an Essence 2 identity, and an Expression 2 identity. Every download is named <CODE>.imx; older Expression 2 files may carry the legacy .avatar extension, which opens the same way. The same file opens on every on-device runtime — Python, Swift and the CLI — and bithuman open tells you which model a file you were given holds.

Where .imx files come from

SourceHow
Showcasebithuman pull <slug> — pre-built avatars from bithuman.ai → Explore, which opens on Essence 2 and Expression 2 agents.
DashboardUpload a portrait + voice samples in bithuman.ai → Studio.
APIPOST /v1/agent/generate returns an agent_code whose .imx you can download.

See Building avatars for the full creation flow and media tips.

Agent codes

The .imx is keyed by an agent code (e.g. A23WJF0199). The cloud runtime and REST API resolve an agent by its code — you don’t ship a file. The on-device SDKs open a local .imx — the file you downloaded for that code — and the key comes from BITHUMAN_API_SECRET in the environment, checked at the first frame:

import bithuman

with bithuman.open("A23WJF0199.imx") as avatar:   # the local file — required on-device
    for image in avatar.render("speech.wav"):      # (height, width, 3) uint8, RGB
        ...

To get the file for a local run, download it by code or slug — bithuman pull <CODE> on macOS or Linux, or GET /v1/agent/{code}/model/download — see Caching for offline use.

Note Use agent_code, never the deprecated figure_id — the old identifier returns a 400.

Caching for offline use

You can also pull the file down and pass it by path. A showcase slug needs no account — bithuman pull downloads it anonymously:

bithuman pull sofia-ramirez
# → ~/.cache/bithuman/showcase/sofia-ramirez.imx

sofia-ramirez (agent code A52DHS2219) is an Essence 2 sample identity from the showcase, about 148 MB. bithuman list prints every showcase slug; a slug that is not in that list is refused with slug '<name>' not found in manifest.

bithuman pull <slug>, bithuman list and bithuman open need no credential for a sample avatar. Pulling your own agent by code, and playing any model with bithuman run or bithuman render, need bithuman login or BITHUMAN_API_SECRET; session time bills at the published rates.

Cache locations by surface:

SurfaceCache location
CLIpulls in ~/.cache/bithuman/showcase/ (samples) and ~/.cache/bithuman/agents/ (your agents); unpacked copies in ~/.cache/bithuman/bundles/
Pythonunpacked copies in ~/.cache/bithuman/avatars/; engine files in ~/.bithuman/deps/
Swift (Expression on Mac/iPad)~/.cache/bithuman/expression/

Downloads are integrity-verified and cached. Later launches skip the download.

One container, one file per model

Each model produces its own per-identity file in that container, downloaded with GET /v1/agent/{code}/model/download (or bithuman pull <code>, with --model when the agent has more than one):

ModelArtifactWhat it is
essence-1.imxThe first-generation identity — a pre-rendered base whose mouth is patched to the audio. Opens in the Python SDK and the CLI’s run.
essence-2.imxThe Essence 2 bundle; size is per identity, so read Content-Length. Licensed weights; renders locally in the CLI, the Python SDK, the Android library and the Swift Essence2 product — the first local play checks the license with the cloud, so it needs your sign-in.
expression-2.imx (older downloads: .avatar): the same container under two names (a few early identities use an older format; bithuman open tells you which)Renders locally in the CLI, Python, Apple and Android, or on the cloud.

Older releases saved Essence 2 files as <CODE>.lebundle.imx, a legacy extension. Such a file keeps working and bithuman open reads it; today’s downloads are named <CODE>.imx. The model is essence-2.

Inspecting an .imx

bithuman open <file> prints the container format, the model family (Family: essence-2 (Essence 2)) and the files inside; --json adds the manifest. It reads the file on your own disk, so it needs no account and no network:

bithuman open ~/.cache/bithuman/showcase/sofia-ramirez.imx

The engine value is a legacy name

bithuman open reports an engine read from the container header (also engine in --json), and the Python runtime quotes the same string verbatim in load errors — for example backend loader for engine='essence2-light'.

These engine ids are legacy names kept for compatibility. They are the literal strings readers parse, spelled here exactly as you will see them:

engine in the headerThe model you actually have
essence1Essence 1 — also the value an older container with no header resolves to
essence2-lightEssence 2 — request it as essence-2
essence2-qualityEssence 2 Max (Enterprise plan only) — not a model you can request on other plans; treat the file as Essence 2
expression2Expression 2 — request it as expression-2

So a current Essence 2 bundle reports engine: essence2-light. The model is Essence 2, requested as essence-2: the engine id names the loader family, not the product, so the value is expected, not a mismatch.

Warning Never send an engine id to the API. model takes essence-2, expression-2, auto, essence-1 or expression-1; any other value returns 400 VALIDATION_ERROR.

File-format stability

The .imx format is forward-compatible within a major version. The first open unpacks the file into that cache, using about its size again on disk; later opens reuse it. Your file is never rewritten.

Where to go next