VideoObject schema for web extraction
This is a ready-to-copy extraction schema for the VideoObject data shape. You describe a video page once as a typed JSON schema, send it to Extracto along with a single video URL, and the page runs through a real headless browser before the response comes back validated against your schema. Instead of writing and re-writing CSS selectors that break the moment a watch page ships a new layout, you name the fields you want (title, description, uploadDate, duration, viewCount, channel, thumbnailUrl, contentUrl) and let the extraction map them. Video pages are a hard target for selector-based scraping precisely because so much of the meaningful data lives in lazy-loaded components, collapsed description panels, and JSON-LD blocks rather than in stable, human-readable DOM nodes. Counts get abbreviated ("1.2M views"), upload dates render as relative strings ("3 weeks ago"), and durations show up both as on-thumbnail overlays and as ISO 8601 strings in structured data. Extracto normalizes those into the types your schema declares: viewCount as an integer, uploadDate as an ISO date, duration as a string you can parse deterministically. The single most important guarantee for video data is the null contract. When a field genuinely is not present, a private upload with a hidden view count, or a livestream that has no fixed duration yet, Extracto returns null for that field rather than inventing a plausible-looking number. That distinction matters more for video than for almost any other shape, because a fabricated view count or a guessed upload date silently corrupts trend dashboards, content audits, and creator analytics without ever throwing an error. Every request also runs through a managed anti-bot bypass layer with proxies handled for you, so consent walls, regional gates, and challenge pages on protected video hosts are handled as part of normal rendering with no setup on your end. The result is one URL in, typed JSON out, validated against the exact shape below.
Fields in a VideoObject schema
The fields teams most often extract for a videoobject, what type each one is, and whether it is usually present.
| Field | Type | Required | Notes |
|---|---|---|---|
| title | string | yes | The video's title as displayed on the watch page. Returning it as a validated string means you get the clean headline text without surrounding markup, badges, or channel suffixes, so titles slot directly into a catalog or search index without per-page cleanup. |
| description | string | optional | The full description body, including text hidden behind a 'show more' collapse that selector scraping often misses. Typed as a string, it arrives expanded; when a creator leaves the description empty, you get null instead of an empty-looking placeholder, so you can tell 'no description' apart from 'failed to read'. |
| uploadDate | string | optional | The publish date in ISO 8601 form (YYYY-MM-DD). Watch pages frequently show relative dates like '3 weeks ago'; receiving a normalized ISO date lets you sort, bucket by recency, and compute age without writing fragile relative-time parsers, and null cleanly signals an unscheduled or hidden date. |
| duration | string | optional | Runtime expressed as an ISO 8601 duration string (for example PT12M30S) so it parses deterministically into seconds. A live or premiere stream with no fixed length returns null rather than a fabricated 0, which keeps 'we could not determine length' separate from 'this video is zero seconds long'. |
| viewCount | integer | optional | Total views as a real integer, not the abbreviated '1.2M' string the page renders. Typed numbers go straight into aggregations and charts with no locale or suffix parsing, and a video whose counter is hidden returns null instead of a misleading zero that would skew averages. |
| channel | string | optional | The uploading channel or author name (the schema.org author/creator concept). Returned as a validated string so you can group videos by creator reliably; for anonymous or removed uploads it returns null rather than guessing a name from unrelated on-page text. |
| thumbnailUrl | string | optional | An absolute URL to the poster image. Because the browser resolves relative and lazy-loaded image sources, you get a fully qualified link you can fetch or store directly, and pages with no resolvable thumbnail return null instead of a broken or partial path. |
| contentUrl | string | optional | The canonical URL of the video resource (the playable or embed URL). Typed as a string URL, it gives you a stable handle to reference or re-fetch the asset; when only a player widget exists with no exposed source, you get null rather than a fabricated link that would 404. |
The schema
Copy this and send it with any URL.
{
"type": "object",
"properties": {
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"uploadDate": {
"type": "string"
},
"duration": {
"type": "string"
},
"viewCount": {
"type": "integer"
},
"channel": {
"type": "string"
},
"thumbnailUrl": {
"type": "string"
},
"contentUrl": {
"type": "string"
}
},
"required": [
"title"
]
} Example output
Validated JSON back, matching the schema.
{
"title": "How to Brew Pour-Over Coffee",
"description": "An illustrative example output. A step-by-step guide to brewing a clean, balanced pour-over coffee at home, covering grind size, water temperature, and pour technique. Values shown here are generic examples, not extracted from any real video.",
"uploadDate": "2024-01-15",
"duration": "PT10M34S",
"viewCount": 1200000,
"channel": "Example Coffee Channel",
"thumbnailUrl": "https://example-videos.com/thumbnails/demo-clip-maxres.jpg",
"contentUrl": "https://example-videos.com/watch?v=demo-clip"
} Try this videoobject schema against a real page in the live demo, or read the docs to use it via the API.