Protoreel
Turn HTML prototypes into frame-perfect social videos — by hand in a small Studio app, or by asking your AI assistant.
Protoreel opens your prototype in a headless browser, plays an interaction (clicks, drags, typing, scrolling) with a smooth on-screen cursor, and films it one frame at a time into an MP4. Because the page's clock only moves when Protoreel says so, videos never stutter or drop frames, whatever machine you run them on. If your prototype makes sound, the sound comes along too.
- Six social formats — 4:5 feed, 9:16 reels, 1:1, 16:9, and two Dribbble sizes — up to 4K
- An MCP server — Claude, Cursor, VS Code and other MCP clients can record videos for you
- A Studio app — perform the interaction yourself, then render it in any format
- Sound — prototypes can hand Protoreel their audio, mixed under the video
- No setup beyond one command — Chromium and ffmpeg are fetched for you
Quick start
You need uv (one line to install). Then:
uvx protoreel setup --folder ~/Prototypes
That downloads Chromium (once), creates the folder, and prints the config for your AI client. Put your .html prototypes in that folder.
Use it from Claude, Cursor or VS Code (MCP)
Claude Desktop / Cowork — open Settings → Developer → Edit Config and add:
{
"mcpServers": {
"protoreel": {
"command": "uvx",
"args": ["protoreel", "mcp", "--folder", "/Users/you/Prototypes"]
}
}
}
If Claude says it can't start the server, replace "uvx" with the full path that which uvx prints (desktop apps don't always see your shell's PATH). protoreel setup prints the snippet with the full path filled in.
Claude Code
claude mcp add protoreel -- uvx protoreel mcp --folder ~/Prototypes
Cursor (.cursor/mcp.json) uses the same block as Claude Desktop. VS Code (.vscode/mcp.json) uses the key "servers" instead of "mcpServers".
Restart the app, then just ask:
"Record checkout.html as a 9:16 video: tap the Add to bag button, wait a second, then open the bag."
"Open the Protoreel studio for like-button.html so I can record it myself."
"Re-render my last take as a 4:5 and a 16:9."
Use the Studio yourself
uvx protoreel studio --folder ~/Prototypes
Pick a prototype, choose a format, press Capture, perform the interaction with your mouse, press Esc, then Render. Every take is saved to takes/, so you (or your AI assistant) can render it again later in another format.
Use the command line
uvx protoreel record like-button.html examples/like-button.json --format 9x16 --zoom 2.4
uvx protoreel render-take like-button_20261013-101500.json --format 16x9 --res 4k
The MCP tools
| Tool | What it does |
|---|---|
list_workspace |
Lists prototypes, recent takes and recent videos |
record_video |
Films a prototype following a script (below) |
render_take |
Films a take captured in the Studio, in any format |
preview_frame |
Returns one frame as an image, to check framing and zoom |
open_studio |
Opens the Studio in your browser |
check_setup |
Checks Chromium and ffmpeg (and can install Chromium) |
Scripts
A script is a list of actions, played in order. Elements are found with CSS selectors at the moment each action starts, so menus that open mid-video work naturally.
{
"start": ["80%", "85%"],
"actions": [
{"wait": 400},
{"click": "#add-to-bag", "dur": 800},
{"wait": 900},
{"type": "Lekki Phase 1", "delay": 60},
{"key": "Enter"},
{"drag": {"by": [0, -220]}, "dur": 900},
{"scroll": {"to": "#reviews"}, "dur": 1000},
{"wait": 1200}
]
}
| Action | Meaning |
|---|---|
{"wait": 500} |
hold still for 500 ms |
{"move": POINT, "dur": 600} / {"hover": POINT} |
glide the pointer to a point |
{"click": POINT, "dur": 500} |
glide there, then press and release ({"click": true} clicks in place) |
{"drag": {"to": POINT} or {"by": [dx, dy]}, "dur": 900} |
press, move, release |
{"down": true} / {"up": true} |
press or release in place |
{"key": "Enter"} |
press a key (names) |
{"type": "Hello", "delay": 70} |
type text, one character every 70 ms |
{"scroll": {"by": [0, 400]} or {"to": POINT}, "dur": 800} |
scroll smoothly |
A POINT is [x, y] in CSS pixels, ["50%", "60%"] of the frame, "#selector", or {"el": "#selector", "x": 0.5, "y": 0.5} for a spot inside an element. Any action can take "ease": smooth (default, like a hand), linear, in, out or inout.
Formats and zoom
| Format | Size at 1080 | Typical use |
|---|---|---|
4x5 |
1080 × 1350 | Instagram / LinkedIn feed |
9x16 |
1080 × 1920 | Reels, TikTok, Shorts |
1x1 |
1080 × 1080 | Square |
16x9 |
1920 × 1080 | Landscape, YouTube, X |
4x3 |
1600 × 1200 | Dribbble |
3x2 |
1800 × 1200 | Dribbble wide |
Zoom (0.6–3.6, default 2) is how large the prototype appears: the page is laid out at format ÷ zoom CSS pixels and rendered sharply at that scale. Resolution (1080, 2k, 3k, 4k) adds pixels without changing the framing.
Sound
Headless browsers can't record their own audio, so prototypes that make sound opt in with one function:
// Return a base64 WAV of the sounds that played between startMs and startMs + durationMs
// (on the page's clock, i.e. performance.now()). A Promise of the string is fine too.
window.__recorderAudio = function (startMs, durationMs) { /* ... */ };
The usual pattern is to log each sound as it plays and replay the log into an OfflineAudioContext. examples/like-button.html shows the whole thing in about 15 lines. Pages without the function produce silent videos.
Folder layout
~/Prototypes/ your .html prototypes (full pages or bare fragments)
~/Prototypes/renders/ finished videos
~/Prototypes/takes/ takes captured in the Studio
Set the folder with --folder, or the PROTOREEL_HOME environment variable (default ~/Protoreel).
Troubleshooting
- "Chromium is not installed" — run
uvx protoreel setup. Behind a strict network? PointPROTOREEL_CHROMIUMat an existing Chrome/Chromium. - The Studio port is busy — another Studio is probably running;
protoreel studio --port 8800picks another. - The video is silent — the page doesn't define
window.__recorderAudio; see Sound. - Clicks miss — use a selector rather than coordinates, and check with
preview_frame.
Contributing
Protoreel is small on purpose and written to be easy to read. Start with docs/architecture.md, then see CONTRIBUTING.md.
License
MIT © Kingsley Mkpandiok
Metadata
Release files for protoreel 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| protoreel-0.1.0.tar.gz | 135.2 kB | With provenance | Details for protoreel-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| protoreel-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for protoreel-0.1.0-py3-none-any.whl |
Total release size: 182.5 kB
Release files / protoreel-0.1.0.tar.gz
| Download URL | protoreel-0.1.0.tar.gz |
|---|---|
| Size | 135.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6a04a01b45339bdd174ff82ef195f064fd8ecc3304320e97a5b591fcc44b2c8c
|
|
BLAKE2b-256 checksum How to use checksums |
7c5cd9308ac6ad3cdeba7adf71312a822ef7971f2dd1b54ab86fa60611f70b2c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / protoreel-0.1.0-py3-none-any.whl
| Download URL | protoreel-0.1.0-py3-none-any.whl |
|---|---|
| Size | 47.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a96b6d37eadd5857cb39aa034d8f447c85e84b8535e9da37369b9e92b55f2742
|
|
BLAKE2b-256 checksum How to use checksums |
8393bdbccb05a63ddf1be9dbe0c9a3dcc5f40f193a3254a0816b1bf00706fd20
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logSecurity for protoreel 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for protoreel-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.