Produce a narrated tutorial video of a web app with Screen Browser...
Screen Browser turns a written guide into a narrated video: it signs in to the customer's deployed app in a real browser, follows the guide, adds the narration and the on-screen effects, and returns an MP4. You write the guide; Screen Browser writes the script. A guide is plain language — what the viewer does and what they see — not selectors, not stage directions. The recorder resolves each step against the live page and remembers what it learned for the next run.
The MCP server is part of the Screen Browser app and signs the user in with OAuth: installing this
plugin, or claude mcp add --transport http screenbrowser https://mcp.screenbrowser.com, is enough —
the first tool call opens the browser for sign-in and consent. If the agent cannot open a browser,
an API key from Settings → API keys goes on the same command as
--header "Authorization: Bearer sb_live_…".
If the screenbrowser MCP tools are not available in the session, stop and ask the user to install
the plugin or register the server; if they are present but every call is refused, ask them to run
/mcp and authenticate.
Connecting needs a Screen Browser account with a plan and a confirmed email address. A user without one can start with a 7-day trial for $3.99 on monthly Starter or Pro (about 5 minutes of video, and bonus minutes in the first paid month): https://screenbrowser.com/pricing/. Say this plainly; don't call it free.
get_credits. A one-minute video costs about 10 credits; a run charges nothing
unless it completes.list_projects; if the app is not there, gather from the user:
the deployed URL to record (staging or production), a demo user that signs in with email and
password only (no OAuth, no 2FA, no captcha, no new-device email), and which attestation applies
(they own the app, a client authorised them, or it is an internal tool). Then create_project with
a login gate — login_success_url_contains when the post-login redirect in the code goes to a
distinct path such as /dashboard, otherwise login_success_text (words only a signed-in user
sees) — and allow_hosts (every host the frontend calls: API subdomain, auth provider, CDN).
Credentials go in variables, never in guides. Narration defaults to English in the language's default
voice; when the user wants another language or a particular voice, list_voices (optionally with a
language) shows the ids, tiers and credits per minute, and create_project / update_project take
language and voice. A single video can use a different voice via start_run's voice.
Mobile web: the same guide can be recorded as a phone or tablet. create_project /
update_project take a default device (desktop, iphone, iphone-max, android,
android-large, ipad, ipad-pro, android-tablet), a frame (portrait 9:16 in a phone
frame, landscape widescreen 16:9 with the phone upright, or none for the bare screen) and a
backdrop (neutral or brand). One run is one device: for a desktop and a phone version,
start two runs of the same guide and pass device to the second. Same credits per minute.{USERNAME} into the field the user sees as the email or username field, {PASSWORD} into the
password field, press the sign-in button, then Confirm something only a signed-in user sees.[CAPTION "…"] line before every action
the viewer should hear about, in the words a narrator would say: the captions are the narration,
spoken verbatim, so a click without one plays in silence and reads as a cut. One short sentence
each; a caption may cover the two or three actions that follow it.
Put a Confirm … line after every navigation or save so a broken flow stops early. For a
phone or tablet run, never write hover steps (a touch screen has no pointer; the recorder
skips them) and name mobile navigation as the user sees it ("the menu button"); keep zoom
factors at 1.4 or below, the screen is small. If a step
creates data, name it so reruns do not collide, or delete it at the end of the guide.validate_guide (kind auth, then main, with project_id) and fix every problem
until passed is true. The check is free and instant: it reads the guide (directives, variables,
secrets typed literally, the "Go to" start, length and cost) without opening the app, so a label
the page does not show still only appears on the first run. Run it after every edit, not only the
first time. Show both guides to the user before
uploading.put_guide auth, put_guide main (give it a name, and a video_title when
the opening should say something other than the name), start_run (with
device, frame, backdrop for a phone or tablet version), then get_run
every 15–30 seconds until is_terminal. Runs take 2–6 minutes; do not start a second run of the
same project while one is in progress. A failed run costs nothing and is the fastest way to learn
what the page really calls things: get_run lists what was resolved and what was learned per step.
If a run fails with error.code login_failed ("Sign-in didn't go through"), check the demo
credentials first; if they are right, the login gate was wrong: fix it with update_project and
start again.put_guide, start_run), which
costs the same as the first take. Then give the user video_url (signed, valid 15 minutes; call
get_run again for a fresh link) and the credits charged, and ask what to change: every note in
plain words is one edit to the guide and one more run. get_run's artifacts also carry the exports: gif (animated GIF of the
video), chapter_gifs (zip, one per chapter), subtitles_vtt / subtitles_srt, and chapters (YouTube's
chapter list) — hand over the ones the user asked for, or all of them for an upload elsewhere. On failure read error.hints, fix the guide, and retry once. Typical
causes: the login gate never appeared, a host missing from allow_hosts, the demo user hit a
captcha, a step that names something the page does not show.css-1x9f2k, sc-bdVaJa, _1a2b3c): they change
with every deploy and validate_guide refuses them. Ids and name= attributes from the templates
are fine when a step needs precision; the syntax for that is in references/guide-syntax.md, but a
good guide rarely needs it.If visible, click "Remind Later", If shown, click "Accept". The recorder
skips an optional step whose element is not on the page instead of failing the run.Screen Browser adds the narration, captions and highlights on its own from the caption lines. Beyond
that, a guide asks for an effect with a directive: a bracketed line placed right before the step it
decorates, or on the same line as the caption for that step —
[HIGHLIGHT "text=New campaign"] [CAPTION "Click New campaign to get started."]. Point at elements
the same human way (text=, label=, role=button:Save, name=), never at a generated class
name. The complete list is in references/guide-syntax.md.
Which effect for which moment; these are the choices that make a demo video look deliberate:
| Moment | Effect |
|---|---|
| The viewer is about to click something | [HIGHLIGHT "text=Save"] before the click; the ring stays until the next action |
| A dense form, card or preview the viewer must read | [ZOOM "css=…" 1.5] aimed at the container (the card, the panel), never at its heading; [ZOOM_OUT] when done |
| A control that needs a sentence beside it | [TOOLTIP "…" on="label=…" placement=right], on the side that does not cover a field the viewer is about to fill |
| Something the video cannot show (what happens later, where data comes from) | [ANNOTATION …], a label pinned to the element; the form is in the reference |
| A new section of the flow | [CHAPTER "Title"], one per section, two to four per video, with a title that matches what follows |
| The start of the video | [HEADLINE "Title"], once, on the first line |
| The end, after the last save | [CONFETTI 1500], once |
| A number, key or address on screen | [BLUR "label=…"] |
Rules that keep it readable: one effect per moment (a ring or a zoom or a tooltip, not two cards on
the screen at once; a zoom on a card with a ring on the same card is the exception that works); a
caption on every action; no tooltip or annotation on top of the thing the next step types into;
zoom factors 1.4–1.6 on desktop and 1.4 or below on a phone. Effects depend on the plan: every plan
has captions, toasts, highlights, dim, annotations, chapters, step numbers, scroll, cursor, blur and zoom;
arrows, tooltips, headlines, fades, freeze, speed and confetti need Pro or above. An effect
outside the plan is skipped at recording time (the step still runs); validate_guide warns about it.
A workspace with a brand (Settings › Brand in the app: logo, colours, font, call to action) gets a
branded opening with the video's title and an ending with its call to action on every video. They
are free: they do not count toward the minutes. The opening shows the guide's video_title, or its
name when there is none, so write it the way a viewer would title the video ("Invite a teammate").
[HEADLINE] on the first line: the opening already
shows the title.update_project sets the project's own choice (Pro and above): bookends_mode: "custom",
opening_style (clean, bold, minimal, product, none), ending_style (clean, bold,
minimal, none), opening_seconds / ending_seconds (3–10), cta_text, fade, and
narrate_title to have the narrator speak over the opening (off by default), with title_line
for the words (plain text up to 100 characters, {title} fills in the video title; empty speaks
the title). bookends_mode: "default" goes back to the
workspace default. Logos, fonts and clips are uploaded in the app, not through the tools.When start_run is refused with insufficient_credits, or get_credits shows the balance is short, do not
retry. Relay the two links from the response to the user verbatim: the one-click top-up link
(top_up_url, opens Stripe Checkout for the suggested pack, no login needed) and the billing page. top_up
(optional pack: small, medium, large) returns the same links on demand — a /topup request from the user
means call it and print the link. Once the user says they have paid, get_credits again and continue.
get_run marks such failures with error.failure_report.available: true (the page never loaded, the login
gate never appeared with correct credentials, a step timed out on an element that was there, a crash).
Then, and only then, ask the user whether to send Screen Browser the evidence — it shares their app's
screenshot, page structure and logs, never credentials — and call report_run_failure with the run id and
their note. Nothing is retried and the guide is not changed; Screen Browser replies on the run. If the
failure is in the guide (a button that does not exist, a wrong label), fix the guide instead.