Skip to main content
To get an avatar video with a transparent background, request the WebM output format on POST /v3/videos. WebM carries an alpha channel; MP4 does not. This is the single most-missed setting — the default output is a standard MP4 with an opaque background, so if you don’t ask for WebM you will never get transparency.
Your avatar must support matting. Transparent output only works when the avatar was trained with matting (background separation) enabled. Matting is enabled by default for recently-created avatars, so most video avatars (Digital Twins and Studio Avatars) support transparent output. If an avatar wasn’t trained with matting, the WebM request is rejected with a clear error — “This video avatar does not support webm output. The avatar must be trained with matting enabled.” — so you can request WebM and handle that error rather than guessing up front. If you hit it, use a more recently-created avatar (or confirm with the avatar’s owner).

Prerequisites

An avatar_id for a matting-trained avatar — matting is the default for recently-created avatars. Use GET /v3/avatars/looks to browse your looks and copy an id.
A voice_id for the voice you want. Use GET /v3/voices to browse available voices. (You can omit voice_id when using an avatar_id — the avatar’s default voice is used.)

The one required switch: output_format

output_format accepts two values:
ValueResult
mp4Default. Standard video, opaque background. No alpha channel.
webmTransparent background — a WebM file with an alpha channel, ready for compositing.
Selecting output_format: "webm" does three things automatically:
  1. Returns a WebM file with a real alpha channel.
  2. Applies background removal for you — you do not need to set remove_background.
  3. Rejects any background value in the same request (you can’t both remove and set a background).
So the minimum change to turn a normal avatar video into a transparent one is adding a single field: "output_format": "webm".

Step 1 — Create the video

Send a POST to /v3/videos with type: "avatar", your avatar and voice, and output_format: "webm":
curl -X POST "https://api.heygen.com/v3/videos" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "avatar",
    "avatar_id": "YOUR_AVATAR_LOOK_ID",
    "script": "Hi! This video has a transparent background, ready to drop onto any scene.",
    "voice_id": "YOUR_VOICE_ID",
    "title": "Transparent Background Demo",
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "output_format": "webm"
  }'
output_format: "webm" already removes the background. Passing "remove_background": true alongside it is redundant but harmless. Do not also pass a background object — with WebM it is rejected.
The response confirms the resolved format so you can verify WebM was accepted:
{
  "data": {
    "video_id": "v_abc123def456",
    "status": "waiting",
    "output_format": "webm"
  }
}
Copy data.video_id for the next step. If data.output_format comes back as mp4, your request did not select WebM — recheck the field name and value.

Step 2 — Poll for completion

Video generation is asynchronous. Poll GET /v3/videos/{video_id} until status is completed:
curl -X GET "https://api.heygen.com/v3/videos/YOUR_VIDEO_ID" \
  -H "x-api-key: YOUR_API_KEY"
StatusMeaning
pendingQueued for processing
processingVideo is being generated
completedReady — video_url points to the .webm file
failedSomething went wrong — check failure_message
When status is completed, data.video_url is a presigned download link to your transparent WebM.

Full example

import requests
import time

API_KEY = "YOUR_API_KEY"
BASE = "https://api.heygen.com"
HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"}

# 1. Create a transparent-background video.
#    output_format="webm" is the ONLY switch you need — it also removes the background.
resp = requests.post(f"{BASE}/v3/videos", headers=HEADERS, json={
    "type": "avatar",
    "avatar_id": "YOUR_AVATAR_LOOK_ID",
    "script": "Hi! This video has a transparent background.",
    "voice_id": "YOUR_VOICE_ID",
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "output_format": "webm",
})
data = resp.json()["data"]
video_id = data["video_id"]
assert data["output_format"] == "webm", "WebM was not selected — check your request"
print(f"Video created: {video_id}")

# 2. Poll until done.
while True:
    detail = requests.get(f"{BASE}/v3/videos/{video_id}", headers=HEADERS).json()["data"]
    print(f"Status: {detail['status']}")
    if detail["status"] == "completed":
        print(f"Transparent WebM: {detail['video_url']}")
        break
    if detail["status"] == "failed":
        print(f"Error: {detail.get('failure_message')}")
        break
    time.sleep(10)

Why MP4 can’t be transparent

MP4 (H.264/H.265) has no alpha channel — the container and codecs simply can’t store per-pixel transparency. Any request that leaves output_format at its mp4 default produces an opaque video, no matter what else you set. Transparency requires a format that supports alpha, which on this API is WebM. If you need a different alpha-capable container (for example MOV/ProRes 4444 for a video editor), render the WebM and transcode it locally.

Common pitfalls

  • Left output_format at the default. Omitting it gives you an opaque MP4. Add "output_format": "webm".
  • Set remove_background: true but kept MP4. Background removal without WebM does not give you a usable transparent file — MP4 can’t carry the alpha channel. Use output_format: "webm" (which removes the background for you).
  • Used an avatar that wasn’t trained with matting. WebM requires a matting-enabled avatar; otherwise the request is rejected with a clear error. Matting is on by default for recently-created avatars — if you hit this, try a more recent avatar. See the warning at the top.
  • Passed a background object together with webm. WebM removes the background and rejects any background value — send one or the other, not both.
  • Expected the file extension to change on its own. The transparency comes from the WebM container returned in video_url, not from renaming an MP4.

Avatar IV, Avatar V, Avatar III, and photo avatars

output_format is a top-level field on the create request, independent of the rendering engine, so transparent background works the same across all avatar engines:
  • Avatar IV (the default engine when engine is omitted) — no change needed; just add output_format: "webm".
  • Avatar V — pass "engine": {"type": "avatar_v"} and "output_format": "webm" together. Transparency is set the same way.
  • Avatar III — pass "engine": {"type": "avatar_iii"} and "output_format": "webm" together. Works with digital twin, studio avatar, and photo avatar looks alike.
  • Photo avatars — use type: "avatar" with the photo-avatar look id and output_format: "webm", same as a Digital Twin.
The transparent-background switch also applies to image-driven videos (type: "image") — set output_format: "webm" there too.
Transparent output is not available for Cinematic Avatar (type: "cinematic_avatar"). That mode has no output_format field.

Next steps