Media Links

Frame.io stores and processes files uploaded to your projects — images, videos, PDFs, and more. When you retrieve a file via the API, the base response includes core metadata like the file name, status, and a view_url for opening it in the Frame.io app. To access the actual file content — the original, a preview, or different quality renditions — you use includes.

This guide explains the media link includes available on the List Files and Get File endpoints, what each one returns, and when to use each.

What are includes?

Includes are optional fields you can request alongside a file response. By default the API returns only core file metadata — name, status, type, timestamps, and view_url. Includes let you opt in to additional data, keeping responses lean when you don’t need everything.

How to add includes

Pass a comma-separated list of include names as the include query parameter on any Get File or List Files request:

Single include
$GET /v4/accounts/{account_id}/files/{file_id}?include=media_links.thumbnail
Multiple includes
$GET /v4/accounts/{account_id}/files/{file_id}?include=media_links.thumbnail,media_links.original
Includes on List Files
$GET /v4/accounts/{account_id}/folders/{folder_id}/files?include=media_links.thumbnail

Includes work the same way on both the single-file and list endpoints. When used on List Files, the includes are resolved for every file in the response.

SDK examples

1import frameio
2
3client = frameio.Frameio(auth="<YOUR_TOKEN>")
4
5file = client.files.get(
6 file_id="93e4079d-0a8a-4bf3-96cd-e6a03c465e5e",
7 include=["media_links.thumbnail", "media_links.original"]
8)
9
10print(file.media_links.thumbnail.url)

Includes that aren’t requested are omitted from the response entirely.

media_links.original

The original uploaded file, exactly as it was uploaded

media_links.thumbnail

A PNG preview image for display purposes

media_links.high_quality

The best available processed rendition

media_links.efficient

The smallest available rendition for low-bandwidth use cases

media_links.video_h264_180

A low-resolution 180p H264 video transcode for streaming and playback

media_links.scrub_sheet

A WebP sprite sheet of video frame thumbnails for building scrubbing UI

media_links.original

Returns signed URLs pointing to the original file exactly as it was uploaded — no processing, no conversion.

Fields

FieldTypeDescription
download_urlstring | nullSigned URL that forces a file download (Content-Disposition: attachment)
inline_urlstring | nullSigned URL that opens the file directly in the browser (Content-Disposition: inline; filename=<name>)

When to use

Use media_links.original when you need the source file — for example, to let a user download the original MOV, MP4, MXF, AVI, PSD, PNG, or TIFF, or to pass the original bytes to another system.

Example request

$GET /v4/accounts/{account_id}/files/{file_id}?include=media_links.original

Example response

1{
2 "data": {
3 "id": "93e4079d-0a8a-4bf3-96cd-e6a03c465e5e",
4 "name": "hero-banner.png",
5 "type": "file",
6 "media_links": {
7 "original": {
8 "download_url": "https://s3.amazonaws.com/...",
9 "inline_url": "https://s3.amazonaws.com/..."
10 }
11 }
12 }
13}

These URLs are temporary signed S3 URLs — they expire. Do not cache or store them; request a fresh URL each time you need one.

media_links.thumbnail

Returns a PNG preview image of the asset, capped at 540px tall. This is a processed rendition — not the original file — and watermarks may be applied depending on your account settings.

Fields

FieldTypeDescription
download_urlstring | nullSigned URL that forces a download of the PNG thumbnail
urlstring | nullSigned URL that serves the PNG thumbnail inline with no Content-Disposition header

When to use

Use media_links.thumbnail when you need to display a visual preview of the asset — for example in a grid view, a gallery, or a file picker. It loads faster than the original and is always a web-safe PNG format.

Example request

$GET /v4/accounts/{account_id}/files/{file_id}?include=media_links.thumbnail

Example response

1{
2 "data": {
3 "id": "93e4079d-0a8a-4bf3-96cd-e6a03c465e5e",
4 "name": "hero-banner.png",
5 "type": "file",
6 "media_links": {
7 "thumbnail": {
8 "download_url": "https://s3.amazonaws.com/...",
9 "url": "https://s3.amazonaws.com/..."
10 }
11 }
12 }
13}

media_links.high_quality

Returns a download URL for the best available processed rendition of the image. For images, Frame.io picks the largest rendition available (image_high > image_full > image_small).

Fields

FieldTypeDescription
download_urlstring | nullSigned URL for the highest quality rendition

When to use

Use media_links.high_quality when you want the best quality version without needing the original — for example, exporting a high-res rendition for downstream processing, or presenting a full-resolution preview.

Example request

$GET /v4/accounts/{account_id}/files/{file_id}?include=media_links.high_quality

Example response

1{
2 "data": {
3 "id": "93e4079d-0a8a-4bf3-96cd-e6a03c465e5e",
4 "name": "hero-banner.png",
5 "type": "file",
6 "media_links": {
7 "high_quality": {
8 "download_url": "https://s3.amazonaws.com/..."
9 }
10 }
11 }
12}

media_links.efficient

Returns a download URL for the smallest available processed rendition. This is the opposite of high_quality — Frame.io picks the lowest resolution rendition available.

Fields

FieldTypeDescription
download_urlstring | nullSigned URL for the smallest/most efficient rendition

When to use

Use media_links.efficient when bandwidth or file size matters more than quality — for example, generating quick previews in a low-bandwidth environment, or feeding a thumbnail pipeline that doesn’t need full resolution.

Example request

$GET /v4/accounts/{account_id}/files/{file_id}?include=media_links.efficient

Example response

1{
2 "data": {
3 "id": "93e4079d-0a8a-4bf3-96cd-e6a03c465e5e",
4 "name": "hero-banner.png",
5 "type": "file",
6 "media_links": {
7 "efficient": {
8 "download_url": "https://s3.amazonaws.com/..."
9 }
10 }
11 }
12}

media_links.video_h264_180

Returns streaming and download URLs for a low-resolution 180p H264 video transcode of the asset.

This is a legacy include. It will be null if a 180p transcode was not generated for the asset. For most use cases prefer media_links.efficient, which selects the best available low-quality rendition rather than relying on a specific transcode existing.

Fields

FieldTypeDescription
download_urlstring | nullSigned URL to download the 180p H264 video
urlstring | nullSigned URL for streaming the 180p H264 video

When to use

Use media_links.video_h264_180 when you need a guaranteed 180p H264 transcode specifically — for example, integrating with a legacy player or pipeline that requires this exact format. If the transcode doesn’t exist for a given asset, both URLs will be null.

Example request

$GET /v4/accounts/{account_id}/files/{file_id}?include=media_links.video_h264_180

Example response

1{
2 "data": {
3 "id": "93e4079d-0a8a-4bf3-96cd-e6a03c465e5e",
4 "name": "interview-clip.mp4",
5 "type": "file",
6 "media_links": {
7 "video_h264_180": {
8 "download_url": "https://s3.amazonaws.com/...",
9 "url": "https://s3.amazonaws.com/..."
10 }
11 }
12 }
13}

media_links.scrub_sheet

Returns a WebP sprite sheet — a single image containing a grid of video frame thumbnails sampled evenly across the video duration. This is used to build video scrubbing UI, where the player shows a preview frame as the user drags across the timeline.

Scrub sheets are generated for video assets only. The include will return null URLs for images, PDFs, and other non-video files.

Fields

FieldTypeDescription
download_urlstring | nullSigned URL to download the WebP sprite sheet
urlstring | nullSigned URL to load the WebP sprite sheet inline
metadataobject | nullTile layout information for extracting individual frames (experimental API only)

metadata fields:

FieldTypeDescription
tile_xintegerNumber of thumbnail columns in the grid
tile_yintegerNumber of thumbnail rows in the grid
thumb_widthintegerWidth of each thumbnail in pixels
thumb_heightintegerHeight of each thumbnail in pixels
paddingintegerGap in pixels between thumbnails
framesintegerTotal number of frames sampled in the sheet

When to use

Use media_links.scrub_sheet when building a custom video player or timeline UI that needs to show a preview thumbnail as the user scrubs. Rather than making a separate request for each frame, the sprite sheet bundles all preview frames into a single image download.

Example request

$GET /v4/accounts/{account_id}/files/{file_id}?include=media_links.scrub_sheet

Example response

1{
2 "data": {
3 "id": "93e4079d-0a8a-4bf3-96cd-e6a03c465e5e",
4 "name": "interview-clip.mp4",
5 "type": "file",
6 "media_links": {
7 "scrub_sheet": {
8 "download_url": "https://assets.frame.io/...",
9 "url": "https://assets.frame.io/...",
10 "metadata": {
11 "tile_x": 10,
12 "tile_y": 10,
13 "thumb_width": 160,
14 "thumb_height": 90,
15 "padding": 1,
16 "frames": 100
17 }
18 }
19 }
20 }
21}

Extracting a frame from the sprite sheet

The sprite sheet is a grid of tile_x columns × tile_y rows. To display the thumbnail for a given frame index (zero-based), calculate its position within the image:

1function getFrameOffset(frameIndex, metadata) {
2 const { tile_x, thumb_width, thumb_height, padding } = metadata;
3
4 const col = frameIndex % tile_x;
5 const row = Math.floor(frameIndex / tile_x);
6
7 return {
8 x: col * (thumb_width + padding),
9 y: row * (thumb_height + padding),
10 width: thumb_width,
11 height: thumb_height,
12 };
13}

You can then use CSS background-position to show the correct tile from the sprite sheet:

1function applyFrameToElement(el, frameIndex, scrubSheet) {
2 const { x, y, width, height } = getFrameOffset(frameIndex, scrubSheet.metadata);
3
4 el.style.backgroundImage = `url(${scrubSheet.url})`;
5 el.style.backgroundPosition = `-${x}px -${y}px`;
6 el.style.width = `${width}px`;
7 el.style.height = `${height}px`;
8}

To map a playback position (in seconds) to a frame index, use the total video duration and the number of frames in the sheet:

1function positionToFrameIndex(currentSeconds, durationSeconds, metadata) {
2 const progress = currentSeconds / durationSeconds;
3 return Math.min(
4 Math.floor(progress * metadata.frames),
5 metadata.frames - 1
6 );
7}

The metadata field is only available on the experimental API version. On the stable v4 API, scrub_sheet returns download_url and url only.

Combining multiple includes

You can request multiple includes in a single API call:

$GET /v4/accounts/{account_id}/files/{file_id}?include=media_links.thumbnail,media_links.original
1{
2 "data": {
3 "id": "93e4079d-0a8a-4bf3-96cd-e6a03c465e5e",
4 "name": "hero-banner.png",
5 "type": "file",
6 "media_links": {
7 "thumbnail": {
8 "download_url": "https://s3.amazonaws.com/...",
9 "url": "https://s3.amazonaws.com/..."
10 },
11 "original": {
12 "download_url": "https://s3.amazonaws.com/...",
13 "inline_url": "https://s3.amazonaws.com/..."
14 }
15 }
16 }
17}

Choosing the right include

GoalInclude to use
Show a preview image in your UImedia_links.thumbnail
Let a user download the original filemedia_links.original
Open the original file directly in the browsermedia_links.originalinline_url
Get the best quality rendition for exportmedia_links.high_quality
Get a small rendition for low-bandwidth usemedia_links.efficient
Stream or download a low-res video (legacy)media_links.video_h264_180
Build a video scrubbing UI with frame previewsmedia_links.scrub_sheet
Navigate a user to the file in Frame.ioUse view_url from the base file response

view_url — available on every file response without needing an include — is a permanent deep-link into the Frame.io web app. It is not a media URL; it opens the Frame.io UI and has no expiry. Use it when you want to direct a user to review or comment on an asset directly in Frame.io, not when you need to serve or download the file programmatically.

Include availability

Media link includes are only populated once Frame.io has finished processing the uploaded file. If you request an include immediately after upload, the URLs may be null while transcoding is in progress. Check the status field on the file object — includes will be available once status is ready.