> ## Documentation Index
> Fetch the complete documentation index at: https://heygen-1fa696a7.mintlify.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Photo Avatar

> Turn a single photo into a talking AI avatar with the HeyGen Photo Avatar API. Upload an image, attach a script, render a lipsynced video starring that photo.

## Prerequisites

<Check>
  A portrait photo (PNG or JPEG) — clear, front-facing, good lighting
</Check>

<Check>
  A `voice_id` for the voice you want. Use `GET /v3/voices` to browse options.
</Check>

## Step 1 — Create a Photo Avatar

Upload your photo and create a Photo Avatar with `POST /v3/avatars`:

<Tabs>
  <Tab title="From URL">
    ```bash theme={null}
    curl -X POST "https://api.heygen.com/v3/avatars" \
      -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "type": "photo",
        "name": "Sarah — Marketing",
        "file": {
          "type": "url",
          "url": "https://example.com/portrait.jpg"
        }
      }'
    ```
  </Tab>

  <Tab title="From Asset ID">
    First upload the image via `POST /v3/assets`, then reference the returned `asset_id`:

    ```bash theme={null}
    # Upload the image
    curl -X POST "https://api.heygen.com/v3/assets" \
      -H "x-api-key: YOUR_API_KEY" \
      -F "file=@portrait.jpg"

    # Create the avatar
    curl -X POST "https://api.heygen.com/v3/avatars" \
      -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "type": "photo",
        "name": "Sarah — Marketing",
        "file": {
          "type": "asset_id",
          "asset_id": "RETURNED_ASSET_ID"
        }
      }'
    ```
  </Tab>
</Tabs>

The response includes an `avatar_item` with an `id` — this is your `avatar_id` for video creation.

## Step 2 — Generate the video

Use `POST /v3/videos` with `type: "avatar"` and the Photo Avatar ID:

```bash theme={null}
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_PHOTO_AVATAR_ID",
    "script": "Hi there! This video was created from a single photo using the HeyGen API.",
    "voice_id": "YOUR_VOICE_ID",
    "title": "Photo Avatar Demo",
    "resolution": "1080p",
    "aspect_ratio": "auto"
  }'
```

## Step 3 — Poll for completion

Video generation is asynchronous. Poll until `status` reaches `completed`:

```bash theme={null}
curl -X GET "https://api.heygen.com/v3/videos/YOUR_VIDEO_ID" \
  -H "x-api-key: YOUR_API_KEY"
```

| Status       | Meaning                          |
| ------------ | -------------------------------- |
| `pending`    | Queued for processing            |
| `processing` | Video is being generated         |
| `completed`  | Ready — `video_url` is available |
| `failed`     | Something went wrong             |

## Full example

```python theme={null}
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 Photo Avatar from a URL
avatar_resp = requests.post(f"{BASE}/v3/avatars", headers=HEADERS, json={
    "type": "photo",
    "name": "Demo Avatar",
    "file": {
        "type": "url",
        "url": "https://example.com/portrait.jpg"
    }
})
avatar_id = avatar_resp.json()["data"]["avatar_item"]["id"]
print(f"Avatar created: {avatar_id}")

# 2. Generate a video
video_resp = requests.post(f"{BASE}/v3/videos", headers=HEADERS, json={
    "type": "avatar",
    "avatar_id": avatar_id,
    "script": "Welcome! This is a Photo Avatar created from a single image.",
    "voice_id": "YOUR_VOICE_ID",
    "resolution": "1080p",
    "aspect_ratio": "auto"
})
video_id = video_resp.json()["data"]["video_id"]
print(f"Video created: {video_id}")

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

## Photo Avatar–specific parameters

These parameters are only available when using a Photo Avatar (`avatar_type: photo_avatar`):

| Parameter        | Type   | Description                                                                              |
| ---------------- | ------ | ---------------------------------------------------------------------------------------- |
| `motion_prompt`  | string | Natural-language prompt to control body motion and hand gestures (e.g. "nodding gently") |
| `expressiveness` | string | `high`, `medium`, or `low` (default: `low`)                                              |

### Example with motion and expressiveness

```json theme={null}
{
  "type": "avatar",
  "avatar_id": "YOUR_PHOTO_AVATAR_ID",
  "script": "Let me show you our quarterly results.",
  "voice_id": "YOUR_VOICE_ID",
  "motion_prompt": "gesturing with hands while presenting",
  "expressiveness": "high"
}
```

## Optional parameters

| Parameter           | Type    | Description                                                                                               |
| ------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `title`             | string  | Display name in the HeyGen dashboard                                                                      |
| `resolution`        | string  | `4k`, `1080p` (recommended), or `720p`                                                                    |
| `aspect_ratio`      | string  | `auto` (recommended — matches the source, falling back to `16:9`), `16:9`, `9:16`, `4:5`, `5:4`, or `1:1` |
| `remove_background` | boolean | Remove the avatar background                                                                              |
| `background`        | object  | Set a solid color (`type: "color"`) or image background                                                   |
| `voice_settings`    | object  | Adjust `speed`, `pitch`, and `locale`                                                                     |
| `callback_url`      | string  | Webhook URL for completion notification                                                                   |

<Warning>
  Photo quality matters. Use a well-lit, front-facing portrait with a neutral expression for the best results. Avoid sunglasses, hats covering the forehead, or extreme angles.
</Warning>

## Using a preset Photo Avatar

You can skip avatar creation and use a public preset avatar instead:

```bash theme={null}
curl -X GET "https://api.heygen.com/v3/avatars/looks?avatar_type=photo_avatar&ownership=public" \
  -H "x-api-key: YOUR_API_KEY"
```

Pick any `id` from the response and use it directly as your `avatar_id` in `POST /v3/videos`.
