Video Frame Extractor: Keyframes & Thumbnails avatar

Video Frame Extractor: Keyframes & Thumbnails

Pricing

from $1.50 / 1,000 frames

Go to Apify Store
Video Frame Extractor: Keyframes & Thumbnails

Video Frame Extractor: Keyframes & Thumbnails

Extract frames from video files, uploads and video podcast feeds: a set number, one every N seconds, scene changes, keyframes or listed times, plus a contact sheet. Skips blank and repeated frames. JPG, PNG or WebP with links. Pay per frame stored.

Pricing

from $1.50 / 1,000 frames

Rating

0.0

(0)

Developer

Enis Bodlli

Enis Bodlli

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Share

Turn videos into images: a set number of frames, one every few seconds, a frame at each scene change, the video's own keyframes, or frames at the times you list, plus an optional contact sheet that shows the whole video on one image. Give it links to video files, web pages that embed a video, video podcast RSS feeds, or upload your own files. Every frame comes back as a JPG, PNG or WebP with a link and its exact timestamp. It is built for people who make thumbnails and previews, teams that feed video into AI vision models, researchers who code footage, and AI agents that need to see what is in a video.

  • Only useful frames, and only those are charged. Black, white and faded frames, and frames that repeat the one before (a slide that stays on screen), are skipped for free.
  • Scenes with their scores, or keyframes for speed. Scene mode gives each cut's strength; keyframe mode reads a long video in a fraction of the time.
  • Pay per frame, $2 per 1,000 frames ($1.50 on Gold), with nothing to pay for failed links, skipped frames or platform usage.

The easiest way to try it: keep the example input and press Start. You get up to six frames and a contact sheet from each of two short films in about 10 seconds.

What you get for each frame

{
"status": "extracted",
"type": "frame",
"videoUrl": "https://media.w3.org/2010/05/sintel/trailer.mp4",
"videoTitle": "trailer.mp4",
"mode": "count",
"frameIndex": 1,
"timestampSeconds": 4.375,
"timecode": "00:00:04.375",
"imageUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/frame-aed5bc55391c5011-00001.jpg",
"imageWidth": 854,
"imageHeight": 480,
"contactSheetUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/contact-sheet-aed5bc55391c5011.jpg",
"durationSeconds": 52.208,
"fps": 24,
"videoCodec": "h264",
"billedCount": 1
}

What you can do with it

  • Thumbnails and preview strips for a video library, a course or a podcast's video episodes.
  • Frames for AI vision models: send the frames to GPT, Claude or Gemini to describe, tag, moderate or search what is in a video, without sending the whole file.
  • Scene and shot lists for editing, research or archive work, with a timecode per cut.
  • Slide capture from recorded talks and webinars: one image per slide, repeats left out.
  • Training data for computer vision: frames at a fixed rate, at the size and format you need.
  • A new video podcast episode, as pictures: point it at the feed and schedule it.

How to use it

  1. Paste one or more links in Video links, or upload files in Upload video files. A direct file link (MP4, MOV, WEBM, MKV, AVI, FLV, MPEG-TS and more), a page that embeds a video file, and a video podcast RSS or Atom feed all work.
  2. Choose How frames are chosen:
    • count: a set number of frames spread evenly over the video (default 10).
    • interval: one frame every few seconds, from 0.1 s upwards.
    • scenes: a frame at each cut or scene change, with its score; lower Scene change sensitivity finds softer cuts.
    • keyframes: the frames the video was encoded around, the fastest way through a long video.
    • timestamps: frames at the times you list, as seconds (90), clock times (1:30) or a share of the video (50%).
  3. Optionally set Start at and End at to work on part of each video, a Maximum width, the Image format and quality, and switch on Make a contact sheet.
  4. Press Start. Frames appear in the dataset as they are stored; open the Overview tab to see them as images, or download the dataset as JSON, CSV or Excel.

How long it takes

Measured on Apify at the default 512 MB on 2026-10-20, with a 10-minute 720p film:

WhatImagesTime
One frame every 10 seconds5610 s
Scene changes, with a contact sheet12317 s
One frame every 0.6 seconds7842 min 17 s

Each video is downloaded once, so a large file adds its download time. Videos are processed one after another; more memory gives the run more CPU, which shortens long videos.

Pricing

You pay per image stored, a frame or a contact sheet, plus Apify's run start of $0.00005 per GB of memory ($0.00005 at the default 512 MB). Platform usage is included, so there is nothing else to pay.

Apify plan tierPer framePer 1,000 frames
Free, Bronze$0.002$2.00
Silver$0.00176$1.76
Gold and above$0.0015$1.50

Worked examples at the Free and Bronze price:

  • The example input, 11 frames and 2 contact sheets: 13 x $0.002 = $0.026.
  • 1,000 frames: $2.00, or $1.76 on Silver and $1.50 on Gold.
  • One frame every 10 seconds from an hour of video: 360 frames, $0.72.
  • Ten thumbnails and a contact sheet for each of 100 videos: 1,100 images, $2.20.
  • A blank or repeated frame, a link that fails, or a video with no usable frame: nothing.

On the Apify free plan, the monthly $5 of credit pays for about 2,500 frames.

Maximum frames per video caps what each video can cost, and you can set a maximum charge per run: the Actor then stores only as many frames as that amount pays for, keeps a place for the contact sheet, and finishes as succeeded with a message that says the limit stopped it. A run that Apify restarts on another server carries on where it stopped and charges no frame twice.

Input

{
"videoUrls": [
"https://media.w3.org/2010/05/sintel/trailer.mp4",
"https://feeds.twit.tv/twit_video_hd.xml"
],
"maxVideosPerFeed": 1,
"mode": "scenes",
"sceneThreshold": 0.3,
"maxFramesPerVideo": 50,
"startTime": "0:30",
"imageFormat": "webp",
"maxWidth": 1280,
"contactSheet": true,
"contactSheetColumns": 5
}
FieldWhat it doesDefault
videoUrlsLinks to video files, pages that embed one, or video podcast feedsexample films
videoFilesUploaded files, or links to records in an Apify key-value storenone
maxVideosPerFeedHow many of a feed's newest videos are processed3
modecount, interval, scenes, keyframes or timestampscount
frameCountFrames per video in count mode10
intervalSecondsSeconds between frames in interval mode10
sceneThresholdScene change sensitivity, 0.01 to 0.990.3
timestampsTimes for timestamps modenone
maxFramesPerVideoAt most this many frames per video in interval, scenes and keyframes100
startTime, endTimeThe part of each video to work onwhole video
skipBlankFramesLeave out black, white and faded frames, freeon
skipDuplicateFramesLeave out a frame that looks the same as the last one kept, freeon
imageFormatjpg, png or webpjpg
maxWidthScale wider frames down to this width; 0 keeps the video's size1280
imageQualityJPG and WebP quality, 1 to 10085
contactSheetOne grid image per video with every frame and its timeoff
contactSheetColumnsFrames per row on the contact sheet4

Output

One dataset row per image: type is frame or contact-sheet. Every row also carries the video's duration, size, frame rate, codec and whether it has sound, and for a feed the feed's and episode's title and date. A link that fails gives one row with status failed and the reason.

[
{
"status": "extracted",
"type": "frame",
"inputUrl": "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/360/Big_Buck_Bunny_360_10s_1MB.mp4",
"sourceType": "file",
"videoIndex": 2,
"videoTitle": "Big_Buck_Bunny_360_10s_1MB.mp4",
"mode": "count",
"frameIndex": 3,
"timestampSeconds": 4.167,
"timecode": "00:00:04.167",
"sceneScore": null,
"imageUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/frame-822a3b8b2647449b-00003.jpg",
"imageKey": "frame-822a3b8b2647449b-00003.jpg",
"imageFormat": "jpg",
"imageWidth": 640,
"imageHeight": 360,
"imageBytes": 37086,
"framesInVideo": 6,
"durationSeconds": 10,
"width": 640,
"height": 360,
"fps": 30,
"videoCodec": "h264",
"hasAudio": false,
"billedEvent": "frame",
"billedCount": 1,
"error": null,
"errorKind": null
},
{
"status": "extracted",
"type": "contact-sheet",
"videoIndex": 2,
"videoTitle": "Big_Buck_Bunny_360_10s_1MB.mp4",
"imageUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/contact-sheet-822a3b8b2647449b.jpg",
"imageWidth": 1308,
"imageHeight": 380,
"framesInVideo": 6,
"billedEvent": "frame",
"billedCount": 1
},
{
"status": "failed",
"type": null,
"inputUrl": "https://www.youtube.com/watch?v=abc",
"imageUrl": null,
"billedCount": 0,
"error": "YouTube links are not supported: this Actor takes frames from video files, web pages that embed a video file, and video podcast feeds. Use a direct link to a video file you may use, or upload it in \"videoFiles\".",
"errorKind": "unsupported-platform"
}
]

The images themselves are in the run's key-value store, named frame-<video>-<number> and contact-sheet-<video>. The RUN_SUMMARY record there counts the videos, frames stored, frames skipped as blank or repeated, failed inputs and what was charged.

Limits

  • No YouTube, TikTok, Instagram, Vimeo, Facebook, X or other platform pages, and no Google Drive or Dropbox share pages. Those links fail with unsupported-platform before any download and cost nothing. Use a direct link to a file you may use, or upload it.
  • No streaming playlists. HLS (.m3u8) and DASH (.mpd) streams are not read; a page whose only video is a stream fails with not-media and costs nothing.
  • Only videos that open without a login. Private, members-only and paywalled videos are not supported.
  • File size follows memory. Up to about 600 MB per video at the default 512 MB, 1.2 GB at 1 GB, and more with more memory.
  • count mode can return fewer frames than asked. A frame that falls on a blank or repeated picture is skipped, not replaced, so the frames stay evenly spread. The interval, scenes and keyframes modes read on past skipped frames to reach their maximum.
  • The whole file is downloaded, even when only part of it is used.
  • No text recognition, captions or AI descriptions. The Actor returns images and timestamps; send the images to the model of your choice.

FAQ

The Actor reads only public files, pages and feeds that open without a login, and it does not get around any blocking. Copyright in a video stays with its owner: frames for analysis, research, search, previews of your own videos or quoting are common, while republishing someone else's frames can need permission. Check the terms of the source and the laws that apply to you; this is not legal advice.

The error field says why in plain words and errorKind gives the cause. The usual ones: the link is a platform page (unsupported-platform), the server answered 404 (not-found) or refused the download (refused), the link is an image, text or a page without a video file (not-media), the file is audio only (no-video), or the file is over the size limit (too-large). A failed link is never charged, and the other links in the run carry on.

Why did I get fewer frames than I asked for?

Blank and repeated frames are skipped for free. A video that is mostly black, a still image or a slide that stays on screen gives fewer frames; switch off Skip blank frames or Skip repeated frames to keep them all. In scenes mode, a calm video has few cuts: lower the sensitivity.

Which mode is fastest for a long video?

keyframes decodes only the keyframes, and count or interval with frames 15 seconds or more apart jumps straight to each time. scenes and dense interval runs read every frame of the chosen range.

Can I use the frames with an AI model?

Yes. Each imageUrl opens without an Apify login, so you can pass it straight to a vision model, or run the Actor from an AI agent through the Apify MCP server and read the dataset back.

Can I use it through the API or on a schedule?

Yes. Start it through the Apify API, the Python or JavaScript client, Make, Zapier or n8n, and save an input as a task to run it on a schedule. Every result has the same fields.

More Actors from this developer