Upload a video once. Fileboy encodes it at several sizes, makes a poster image, and serves it as adaptive HLS or DASH streaming. Play it with a component, a script tag, an iframe or your own player.
Fileboy stores the original file and returns a video id. The video starts out pending.
In the background it encodes renditions at 240p, 360p, 480p, 720p and 1080p, and a separate audio track, and cuts each into five second fragments. Only sizes up to the height of your original are made, so a 360p source is never upscaled.
It takes a frame from the video as the poster image. You can replace it with your own.
Once the video is ready it makes the seek-preview thumbnails, the small frames shown above the progress bar. If that fails, the video still plays.
When encoding finishes the video is ready, and a
video.readyvideo.failedPlayers ask for a manifest, a small file that lists the renditions. They pick a quality that suits the viewer's connection and switch as it changes.
Adaptive streaming as HLS or DASH from one upload.
An automatic poster image, or your own.
Seek-preview thumbnails as a sprite sheet with WebVTT and JSON, shown by the Fileboy player and readable by Plyr, Video.js and most other players.
Captions and transcripts, one per language, shown in the player.
A player for React, the same player from a script tag, and an iframe embed page for any website.
Player branding: your colours, a logo with a link, the controls you choose and autoplay, muted and loop defaults, set once for the app or per video, with readable contrast kept for you. The player never shows a Fileboy logo.
A play count and the time of the last play on every video.
A description that shows on the watch page and in link previews, plus private tags and your own key-value metadata for matching videos to your records.
Webhooks for uploaded, ready, failed and deleted videos, carrying the video's tags and metadata.
The management API to list, find (by tag or metadata), update and delete videos from your server. Deleting a video removes the original, every rendition, the posters, the transcripts and the thumbnails.
When a viewer points at or drags along the progress bar, the player shows a small frame from that moment. Fileboy makes these for every video it processes: a sprite sheet of frames, and a WebVTT file that says which part of the sheet covers which part of the video. The Fileboy player, and the share, watch and embed pages, find them on their own.
1 2 3 4 5 6 7 8# WebVTT: one cue per frame, pointing at its region of a sprite sheet GET https://api.fileboy.io/videos/VIDEO_ID/thumbnails.vtt # The same as a JSON storyboard: tile size, sheets and every tile's time and position GET https://api.fileboy.io/videos/VIDEO_ID/thumbnails.json # Sheet n (the VTT and JSON link to these for you) GET https://api.fileboy.io/videos/VIDEO_ID/thumbnails/0.jpg
1 2 3 4 5 6 7WEBVTT 00:00:00.000 --> 00:00:01.000 https://api.fileboy.io/videos/VIDEO_ID/thumbnails/0.jpg?v=3f9a1c2e7b4d5a60#xywh=0,0,192,108 00:00:01.000 --> 00:00:02.000 https://api.fileboy.io/videos/VIDEO_ID/thumbnails/0.jpg?v=3f9a1c2e7b4d5a60#xywh=192,0,192,108
1 2 3 4 5 6 7 8 9// <fileboy-player video-id="VIDEO_ID"> needs nothing: it finds them itself // Plyr new Plyr(video, { previewThumbnails: { enabled: true, src: "https://api.fileboy.io/videos/VIDEO_ID/thumbnails.vtt" }, }) // Video.js, with a VTT thumbnails plugin such as videojs-vtt-thumbnails player.vttThumbnails({ src: "https://api.fileboy.io/videos/VIDEO_ID/thumbnails.vtt" })
Videos up to 100 seconds get a frame every second. Longer videos get at most 100 frames, spread evenly: every 6 seconds for 10 minutes, every 40 seconds for an hour.
Tiles keep the video's shape inside 192 by 192 pixels (192x108 for 16:9), on one JPEG sheet. Players only download it when a viewer first points at the progress bar.
They follow the video's access. In an app that requires signed URLs, add the video's signature to the VTT or JSON URL. The sheet URLs inside carry it on, so one
signVideoGET /videos/:id/datathumbnails.statusnonependingprocessingreadyfailedskippedthumbnails_not_foundA video uploaded before November 2026 may not have them yet. To make or remake one video's now, open it in the dashboard and press Generate on the Thumbnails tab. It takes a few seconds and does not change the video.
A video reports its state when you fetch its data (
GET /videos/:id/dataextractionStatus (video data)
pending
The upload is stored and waiting for a worker.
processing
Encoding is running.
done
Every rendition exists and the video can be played.
error
Encoding failed. statusMessage says why.
The management API reports the same thing as
statuspendingprocessingreadyfailedEach plan lists a video allowance, separate from the file limit (Free: 3, Pro: 50, Max: 200). It is a guide for choosing a plan rather than a hard cap today. See pricing.
The shared demo key cannot upload video. Create a free app to try it. The free plan includes three videos.
By default playing a video does not need a key: anyone who has a video's id can watch it, so treat ids like unlisted links. To choose who can watch, turn on signed URLs for the app and sign each video on your server. There is no DRM.
This is on-demand video. It does not do live streaming, and it does not edit video or burn a watermark into it (a branding logo is drawn by the player, over the video).
Every request to a manifest counts as a play, which is what the play count shows.
If video is the centre of your product, read how Fileboy compares with Mux and Cloudflare Stream before you commit.