// FREE TOOL · VIDEO SCHEMA GENERATOR
Video schema generator
Describe one video; get VideoObject JSON-LD with an upload time that carries its timezone, a runtime in real ISO 8601, chapter markers pointing at the right timestamps — and a caption block on the page that says the same thing.
Unique per video. Two videos on a site should not share a title.
BMP, GIF, JPEG, PNG, WebP, SVG or AVIF. Minimum 60x30, larger preferred, and the URL has to stay stable.
Leave this empty and Google reads the date in Googlebot's timezone, not yours.
Type it however you like — 18:42, 1:02:30, 742, or PT18M42S. It comes out as ISO 8601.
Used to build the chapter links, which must point at this same path with a time parameter.
Give Google your own key moments and it uses them instead of guessing segments.
Everything runs in this page. No title, URL or view count leaves your browser.
How to generate video schema
Three required properties, one date format that trips almost everyone, and two URL fields that are not the page you are on. The generator writes the markup and a caption block from the same values.
- Title and thumbnail first. Both are required, and both must be unique to this video. A thumbnail is only useful to Google if the URL stays the same next month — a CDN that rotates URLs quietly costs you video indexing.
- Give the upload time an offset. The date alone is valid; the date with a time and a UTC offset is unambiguous. Without an offset Google reads the timestamp in Googlebot's timezone, which is not yours.
- Type the runtime however you think of it. Eighteen forty-two, one-oh-two-thirty, a raw second count, or the ISO form. The output is always the ISO 8601 duration the property expects.
- Point contentUrl at the file, embedUrl at the player. Neither is the page a reader lands on. The generator refuses a contentUrl that looks like a web page, because that is the single most common mistake in video markup.
- Add chapters and paste both outputs. Chapter links are built from the watch page URL with a time parameter, which is the form Google requires. The JSON-LD goes in the watch page; the caption block goes under the player.
uploadDate: the property that is wrong on most pages that have it
A video schema generator turns a video's details into VideoObject JSON-LD — the structured data Google reads for a video's title, thumbnail, runtime and key moments. Three properties are required: name, thumbnailUrl and uploadDate. The third is where markup goes subtly wrong.
Google's documentation says uploadDate is the date and time the video was first published, in ISO 8601 format, and adds: we recommend that you provide timezone information; otherwise, we will default to the timezone used by Googlebot. A bare 2026-08-14 is accepted. A premiere at 21:00 local time, written without an offset, can be read as a different calendar day — which matters when freshness is the whole point of publishing it.
Three shapes, in increasing order of how much you have told Google:
"uploadDate": "2026-08-14" // valid, no time at all
"uploadDate": "2026-08-14T09:30:00" // time, but whose clock?
"uploadDate": "2026-08-14T09:30:00+02:00" // unambiguous
The same recommendation applies to expires, and Google adds one instruction people ignore: do not supply expires at all if the video does not expire. An empty or far-future expiry is not neutral — it is a claim.
Duration is a duration, contentUrl is a file
duration takes an ISO 8601 duration, not a clock time and not a number of seconds: PT00H30M05S is thirty minutes and five seconds. This form accepts whatever you actually have — 18:42, 1:02:30, 742, or the ISO string — and emits the ISO one. There is no reason for a human to hand-convert this, and every reason for a tool to refuse a value it cannot parse rather than passing it through.
The two URL properties are where video markup most often fails silently:
contentUrlis the video file's actual content bytes. Google's page says it in bold type: don't link to the page where the video lives. It should end in one of the file types Google can process — mp4, webm, mov, mkv and eighteen others — and it must not be a data URL.embedUrlis the player, usually whatever sits in thesrcof your embed element. Also not the page.- Google recommends providing
contentUrlwhen you can, because it is the most effective way for it to fetch the video;embedUrlis the fallback.
This generator treats a contentUrl with no file extension, or with an HTML-ish one, as an error rather than a warning. On a page that already validates everywhere else, that one field is usually the reason the video never appears.
Thumbnails and chapters, with the numbers Google actually publishes
Thumbnail rules are concrete enough to check, and rarely checked:
| Rule | Value |
|---|---|
| Formats | BMP, GIF, JPEG, PNG, WebP, SVG, AVIF |
| Size | Minimum 60x30 pixels, larger preferred |
| Transparency | At least 80% of pixels must have an alpha value above 250 |
| Stability | A single unique, stable URL per video — expiring CDN URLs break video indexing |
| Access | Reachable by Googlebot and Googlebot Images: not blocked by robots.txt, not behind a login |
Chapters are the Clip type nested in hasPart, and they carry a rule that most tools skip: the clip URL must point to the same URL path as the video with additional query parameters that specify the time. Give this form your watch page URL and each chapter comes out as that URL plus ?t= and the offset in seconds — not a fragment, not a different host, not a bare page link. The tool also rejects a chapter that starts after the video ends, which is what a mistyped timestamp looks like from Google's side.
One thing markup cannot fix: the video has to be embedded on the page, visible, and not hidden behind other elements. Structured data describes a video that is there; it does not conjure one.
Why there is a second output
Most video generators stop at the JSON-LD. This one also writes a caption block — title, description, publication timestamp, runtime, chapter table — carrying exactly the strings the markup declares.
That is partly the house rule behind every tool here: one source, two outputs, no drift. It is also practical. A watch page whose only description of the video is inside a script tag gives a reader nothing, gives an AI answer engine nothing to quote, and gives you no way to notice when the markup has gone stale except by opening a validator. A visible chapter list with the same timestamps is checkable at a glance.
The same principle, applied to questions and answers, is the FAQ schema generator; applied to a recipe's ingredients and steps, the recipe schema generator, which has the tighter version of this rule because a recipe's marked-up steps are the ones Google shows.
// FAQ
What is a video schema generator?
A video schema generator turns a video's details into VideoObject JSON-LD — the structured data Google reads for a video's title, thumbnail, runtime and key moments. This one also writes a visible caption block carrying the same values, and checks the rules Google attaches consequences to.
What is required in VideoObject structured data?
Three properties: name, thumbnailUrl and uploadDate. Description, duration, contentUrl and embedUrl are recommended. Without the required three, Google may not be able to extract any information about the video at all.
Does uploadDate need a timezone?
It is not mandatory, but Google recommends it and states the fallback explicitly: without timezone information it defaults to the timezone Googlebot uses. For a video published in the evening that can shift the publication date by a day, so give the date, the time and a UTC offset.
What format does the duration property take?
ISO 8601 duration — PT00H30M05S means thirty minutes and five seconds. It is not a clock time and not a plain number of seconds. This generator accepts 18:42, 1:02:30, 742 or the ISO string and always emits the ISO form.
What is the difference between contentUrl and embedUrl?
contentUrl points at the video file's actual bytes — the mp4 or webm. embedUrl points at the player. Neither is the page the video is embedded on; Google's documentation says explicitly not to link to the page where the video lives. Provide contentUrl when you can, because it is the most effective way for Google to fetch the video.
What are the thumbnail requirements?
BMP, GIF, JPEG, PNG, WebP, SVG or AVIF, minimum 60 by 30 pixels with larger preferred, at least 80% of pixels effectively opaque, reachable by Googlebot and Googlebot Images, and served from a single stable URL per video. Rotating CDN URLs are a common reason videos stop being indexed.
How do I add chapters or key moments?
Nest Clip objects in hasPart, each with a name, a startOffset in seconds, and a url that points at the same path as the watch page with a time query parameter added. Supplying your own clips tells Google what timestamps and labels to use instead of the segments it would pick itself.
Is the watch page indexed, or only the video?
Checking your own domain is free: every page with its live HTTP status and Google's index verdict, impressions and average position against the previous window, and traffic by source with AI engines listed separately. One command, from inside your agent.
$ npm i -g @clize/clize && clize install $ clize seo check --domain yourdomain.com[ Agent SEO by Clize → ]