---
title: "Get Video Scenes"
method: GET
path: "/v3/videos/{video_id}/scenes"
tags: ["Videos"]
---

# Get Video Scenes

`GET /v3/videos/{video_id}/scenes`

## Request

- Base URL: `https://api.heygen.com`
- URL: `https://api.heygen.com/v3/videos/{video_id}/scenes`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

Returns a video's scenes as it stands now, with the `edit_version` to send when editing. Each scene has a `background`, placed `elements` and a `script`. Skip element types you do not recognize. Geometry, text content, animations and background music are not described. A video whose editor document is still being prepared returns `409 resource_not_ready`; retry after it advances.

## Path parameters

- `video_id` string, required

## Response `200`

Successful response

- object
  - `error` object, nullable
  - `data` VideoScenesResponse: The composite document: one video's context and every one of its scenes.
    - `video_id` string, required: The video these scenes belong to.
    - `edit_version` string, required: Opaque version of the editor document returned by this request. Pass it unchanged when requesting an edit so the server can reject a document that changed before submission. This submission-time check does not lock the document while the asynchronous agent applies the edit.
    - `video` VideoContext, required: Video-level facts needed to make sense of the scenes.
      - `title` string, nullable: The video's current title. Editor saves update it.
      - `aspect_ratio` '16:9' | '9:16' | '4:5' | '5:4' | '1:1' | 'auto': Output video aspect ratio. - ``16:9`` / ``9:16``: classic landscape / portrait. - ``4:5`` / ``5:4`` / ``1:1``: social-media-friendly ratios. Output is short-edge anchored to the requested resolution (e.g. ``1080p`` 1:1 → 1080x1080, ``1080p`` 4:5 → 1080x1350). - ``auto``: preserve the source's aspect ratio. The dimensions are derived from the avatar's source frames (``avatar_id``) or the uploaded image (``image_url`` / ``image_asset_id``), short-edge anchored to the requested resolution and capped at the tier's long edge. Falls back to ``16:9`` when source dimensions can't be read.
      - `resolution` '4k' | '1080p' | '720p': Output video resolution. `4k` is available for Avatar III digital twins and studio avatars.
      - `caption` VideoCaption: Whether the video involves captions.
        - `enabled` boolean, required: Whether captions are enabled for this video.
      - `brand_glossary_id` string, nullable: Brand glossary applied to this video's speech.
    - `scenes` Scene[]: Every scene in the video, in the video's own order, which is playback order unless the video branches. Never paginated.
      - `id` string, required: Identifier of this scene within the video.
      - `background` union: What fills the frame behind this scene's elements.
        - ColorBackground: A solid colour filling the frame behind the scene's elements.
          - `type` 'color': Background type discriminator.
          - `color` string, required: Hex colour, e.g. '#f6f6fc'.
        - ImageBackground: A whole-frame image.
          - `id` string, required: Opaque identifier of this element within the video. Not to be parsed, sorted, or assumed to encode anything. Stable across edits and across regeneration of the video.
          - `type` 'image': Background type discriminator.
          - `url` string, nullable: URL of the image. Present when the video records a link for this background and, if that link is signed, it is not at or near its deadline. Absent when no link is recorded, or the only recorded link has lapsed. Only the deadline is checked, so a present URL is not a promise that it resolves: it may name an object that has since moved, or a host the customer supplied. Signed links expire, so download what you need rather than storing the URL.
        - VideoBackground: A whole-frame video clip.
          - `id` string, required: Opaque identifier of this element within the video. Not to be parsed, sorted, or assumed to encode anything. Stable across edits and across regeneration of the video.
          - `type` 'video': Background type discriminator.
          - `url` string, nullable: URL of the clip. Present when the video records a link for this background and, if that link is signed, it is not at or near its deadline. Absent when no link is recorded, or the only recorded link has lapsed. Only the deadline is checked, so a present URL is not a promise that it resolves: it may name an object that has since moved, or a host the customer supplied. Signed links expire, so download what you need rather than storing the URL.
          - `playback` string, nullable: How the clip is reconciled to the scene. Same values as a video element's playback.
          - `trim` VideoTrim: Seconds trimmed from each end of a clip.
            - `start_offset` number, required: Seconds trimmed from the start of the clip.
            - `end_offset` number, required: Seconds trimmed from the end of the clip.
          - `volume` number, nullable: Clip audio volume. 1.0 = source level, 0.0 = silent.
          - `speed_multiplier` number, nullable: Playback speed multiplier. 2.0 = twice as fast.
      - `elements` union[]: Every element this scene places, in the video's own order.
        - union
          - AvatarElement: An avatar performing the scene's speech. Carries what a v3 create request can set per avatar, so what is read back here is what can be sent back. Fields are added as callers need them, and a new one is not a breaking change. Output resolution is a whole-video setting, reported on the video rather than per avatar.
            - `id` string, required: Opaque identifier of this element within the video. Not to be parsed, sorted, or assumed to encode anything. Stable across edits and across regeneration of the video.
            - `type` 'avatar': Element type discriminator.
            - `avatar_id` string, required: The avatar look performing this scene.
            - `engine` 'avatar_vi' | 'avatar_v' | 'avatar_iv' | 'avatar_iii': Coarse UI-facing tier. This is what the user sees in the engine dropdown.
            - `expressiveness` 'high' | 'medium' | 'low': Avatar expressiveness level for photo avatars.
            - `motion_prompt` string, nullable: Motion description authored for this avatar.
          - ImageElement: An image placed in the scene.
            - `id` string, required: Opaque identifier of this element within the video. Not to be parsed, sorted, or assumed to encode anything. Stable across edits and across regeneration of the video.
            - `type` 'image': Element type discriminator.
            - `url` string, nullable: URL of the image. Present when the video records a link for this element and, if that link is signed, it is not at or near its deadline. Absent when no link is recorded, or the only recorded link has lapsed; the element is still reported either way, so an image with no URL is one this read could not link to rather than an element this API does not describe. Only the deadline is checked, so a present URL is not a promise that it resolves: it may name an object that has since moved, or a host the customer supplied. Signed links expire, so download what you need rather than storing the URL.
          - VideoElement: A video clip placed in the scene.
            - `id` string, required: Opaque identifier of this element within the video. Not to be parsed, sorted, or assumed to encode anything. Stable across edits and across regeneration of the video.
            - `type` 'video': Element type discriminator.
            - `url` string, nullable: URL of the clip. Present when the video records a link for this element and, if that link is signed, it is not at or near its deadline. Absent when no link is recorded, or the only recorded link has lapsed. Only the deadline is checked, so a present URL is not a promise that it resolves: it may name an object that has since moved, or a host the customer supplied. Signed links expire, so download what you need rather than storing the URL.
            - `playback` string, nullable: How the clip is reconciled to the scene: 'freeze' holds the last frame, 'loop' repeats it, 'fit_to_scene' changes speed to match, 'full_video' plays it whole and drives the scene's length.
            - `trim` VideoTrim: Seconds trimmed from each end of a clip.
              - …
            - `volume` number, nullable: Clip audio volume. 1.0 = source level, 0.0 = silent.
            - `speed_multiplier` number, nullable: Playback speed multiplier. 2.0 = twice as fast.
          - TextElement: On-screen text, plain or styled, reported as the text it displays. Styling (font, size, colour, alignment) is not described: like geometry, it would need a contract this response does not have. Styled text is flattened to its characters with one newline between paragraphs, which is exactly the text a template variable is matched against.
            - `id` string, required: Opaque identifier of this element within the video. Not to be parsed, sorted, or assumed to encode anything. Stable across edits and across regeneration of the video.
            - `type` 'text': Element type discriminator.
            - `text` string, required: The text as displayed. Paragraphs of styled text are joined with newlines.
          - PlaceholderElement: An element this version names but does not describe. Exists so a scene's ``elements`` array is never a filtered view presented as a complete one: a caller iterating it sees every element the scene places. Carries exactly two fields: which element this is, and what kind of thing it is. **Absence of content is not by itself proof that an element is undescribed.** A described category can serialize with nothing but an id and a type when every optional field happens to be unavailable, and one case is reachable today: an image with no usable link carries no ``url``, leaving ``{id, type}``. Read the ``type`` to tell them apart. ``avatar``, ``image``, ``video`` and ``text`` are described, so a bare one of those is a described element missing an optional value rather than an unexpanded node. The ``id`` matters most here. Two masked elements in one scene are otherwise identical on the wire, so without it a caller can see that the scene places two things and nothing else about either.
            - `id` string, required: Opaque identifier of this element within the video. Not to be parsed, sorted, or assumed to encode anything. Stable across edits and across regeneration of the video.
            - `type` string, required: The element's category. An **open set**: new values may be added, so treat an unrecognized one as an element to skip rather than an error. Several kinds of element can share one value, so a category says what an element is rather than naming a single underlying kind. Every value is permanent except 'other', which means 'a kind of element this API does not yet categorise' and may be replaced by a more specific category later.
          - ContainerElement: An element that holds other elements: a group, or a mask. A scene lists the container, not its contents, so a scene holding one group of five images lists a single element while five things render. Walking a scene's composition means recursing into ``children``. A mask matters more here than a group: a group conveys linkage this response does not express, while a mask conveys clipping, so treating a masked image as a plain image asserts a composition that renders differently in kind.
            - `id` string, required: Opaque identifier of this element within the video. Not to be parsed, sorted, or assumed to encode anything. Stable across edits and across regeneration of the video.
            - `type` string, required: The container's category, e.g. 'group' or 'mask'.
            - `children` union[]: The elements this container holds, each described exactly as a top-level element would be.
              - …
      - `script` union[]: This scene's audio sources in order, each one synthesized speech, uploaded audio, or a silence. The create API's per-scene `script` is narrower: it is the text of a single one of these entries.
        - union
          - TextScriptEntry: Synthesized speech: a script delivered by a voice.
            - `id` string, required: Opaque identifier of this script entry within the video. Not to be parsed, sorted, or assumed to encode anything. The same id under two scenes means one entry is shared between them: its text belongs to both, and concatenating both scenes' scripts would synthesize the shared words twice.
            - `type` 'text': Script entry type discriminator.
            - `text` string, required: The script, verbatim, including inline markup. Empty when the scene was left unfinished.
            - `voice_id` string, nullable: The voice delivering this script.
            - `voice_settings` ScriptVoiceSettings: The voice tuning applied to this script. A value here can fall outside the range the create API accepts, so validating it against a create request's schema will reject videos it should accept.
              - …
            - `trim_to_speech` boolean, nullable: Deprecated and ignored: the narration is kept whole, without trimming silence, whatever this says.
          - AudioScriptEntry: Uploaded audio played as the scene's speech.
            - `id` string, required: Identifier of this script entry within the video.
            - `type` 'audio': Script entry type discriminator.
            - `audio_url` string, nullable: URL of the audio. Present when the video records a link for this entry and, if that link is signed, it is not at or near its deadline. Absent when no link is recorded, or the only recorded link has lapsed. Only the deadline is checked, so a present URL is not a promise that it resolves: it may name an object that has since moved, or a host the customer supplied. Signed links expire, so download what you need rather than storing the URL.
          - SilenceScriptEntry: A held silence, with no words spoken over the scene.
            - `id` string, required: Identifier of this script entry within the video.
            - `type` 'silence': Script entry type discriminator.
            - `duration` number, nullable: How long the silence is held, in seconds. Absent where the number does not describe what renders — on a scene whose video clip plays in full, the clip's own length governs the scene.

## Other responses

- `400`: Invalid request parameters
- `401`: Authentication failed
- `404`: Resource not found
- `409`: Conflict
- `429`: Rate limit exceeded

## Changes

- **2026-11-03** `7dfa5e59b4f5`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/heygen/apis/heygen-external-api/changes/v3/videos/:video_id/scenes/get.md)

---

[API](https://skmtc.dev/heygen/apis/heygen-external-api.md) - [All operations](https://skmtc.dev/heygen/apis/heygen-external-api/llms.txt) - [OpenAPI document](https://skmtc.dev/heygen/apis/heygen-external-api/revisions/7dfa5e59b4f5?raw)
