Start free

Course schema for web extraction

Online course pages on platforms like Coursera, Udemy, edX and bootcamp sites pack a lot of structured facts into a noisy layout: the title, the institution or company that offers it, an instructor bio, a star rating, a duration estimate, a difficulty level and a price that often sits behind a discount banner or loads via JavaScript. The Course schema gives you all of that as clean, typed JSON from a single course URL. Instead of writing and maintaining CSS selectors that break the moment a platform reships its front end, you describe the fields you want in plain language and Extracto runs the live page through a real headless browser, reads it, and maps the content to your schema. Every value is validated against the type you declared, so price comes back as a number you can compare, rating comes back as a number you can sort on, and free text comes back as strings. When a page genuinely does not expose a field (a free course with no price, a self-paced track with no fixed duration, a platform that hides instructor names) Extracto returns null for that field rather than inventing a plausible looking value. That null-not-guess behavior is the difference between a dataset you can trust for a course comparison table or a catalog ingest and one you have to manually re-check. Because each request includes a managed anti-bot bypass layer with proxies handled for you, the schema works the same way whether the course page is a static document or a heavily protected, JavaScript-rendered single-page app. You point at one URL per call, so this is course-page extraction, not a crawler that wanders a whole catalog. Copy the schema below, swap in your target URL, and you have a typed course feed in one request.


Fields in a Course schema

The fields teams most often extract for a course, what type each one is, and whether it is usually present.

Field Type Required Notes
name string yes The full title of the course as shown on the page, for example 'Machine Learning Specialization'. Returning it as a validated string keeps titles consistent across rows when you build a comparison table, instead of you parsing the page <title> tag or a heading selector that varies per platform.
provider string yes The institution or company offering the course, such as a university, a vendor like Google or IBM, or the platform itself. Typing it as a string lets you group and filter a catalog by provider; if a page only credits an individual and names no organization, you get null rather than a guessed brand.
description string optional The marketing or syllabus summary describing what the course covers. As a string field it captures the page's own copy verbatim, which is useful for search indexing or de-duplication, and you avoid scraping nested layout blocks by hand with selectors.
price number optional The course price as a numeric value, so 49.99 not the string '$49.99'. Returning it typed means you can sort, filter under a budget, or compute averages directly. Free courses and pages that hide price behind a login return null instead of 0, so you never confuse 'free' with 'unknown'.
duration string optional The stated length of the course, such as '6 weeks' or 'approx. 40 hours'. Platforms express this inconsistently, so it stays a string to preserve the original unit; self-paced courses with no fixed duration return null rather than a fabricated estimate.
level string optional The difficulty or audience level, typically 'Beginner', 'Intermediate' or 'Advanced'. Keeping it as a string captures whatever vocabulary the platform uses; describing the field beats targeting a badge selector that moves around the page, and unlabeled courses come back null.
rating number optional The aggregate learner rating as a number, for example 4.7, drawn from the page's review summary. Typed as a number it sorts and thresholds correctly ('show courses above 4.5'). Courses with no reviews yet return null, which is honest, rather than a placeholder like 0 that would skew rankings.
instructor string optional The name of the lead instructor or educator credited on the page. As a string this powers instructor-level lookups; when a course lists a team, an organization, or no named teacher, you get null instead of Extracto picking one name to fill the slot.

The schema

Copy this and send it with any URL.

{
  "name": "string",
  "provider": "string",
  "description": "string",
  "price": "number",
  "duration": "string",
  "level": "string",
  "rating": "number",
  "instructor": "string"
}

Example output

Validated JSON back, matching the schema.

{
  "name": "Introduction to Data Science",
  "provider": "Example Academy",
  "description": "An illustrative foundational program covering data wrangling, exploratory analysis, and basic machine learning, with hands-on projects in Python. This is a generic example, not extracted from a live page.",
  "price": 59,
  "duration": "approx. 2 months at 10 hours a week",
  "level": "Beginner",
  "rating": 4.6,
  "instructor": "Jane Educator"
}

Try this course schema against a real page in the live demo, or read the docs to use it via the API.

Course schema: FAQ

Does this schema work on course platforms that block scrapers or render with JavaScript?
Yes. Every Extracto request runs the live page in a real headless browser, so JavaScript-rendered course pages and single-page apps load fully before extraction. Each request also includes a managed anti-bot bypass layer that handles protected sites such as Cloudflare, DataDome and PerimeterX, with proxies managed for you and no setup on your side. The one thing it cannot reach is login-gated content that needs your session cookies, for example a course only visible inside a paid enrollment; that scenario is available on the Enterprise plan.
What happens when a course page is missing the price, rating, or instructor?
Extracto returns null for that specific field and still fills in everything else it can read. It never guesses a plausible number or name to make the record look complete. So a free course returns null for price rather than 0, a brand new course with no reviews returns null for rating rather than a placeholder, and a course taught by a team with no single named lead returns null for instructor. This null-not-guess rule is what makes the output safe to load directly into a catalog or comparison table without manual re-checking.
Why describe fields instead of writing CSS selectors for each platform?
Course platforms reship their front ends often, and the same field (say the price or the level badge) lives in a different DOM location on Coursera, Udemy and edX. CSS selectors break on every one of those changes and have to be maintained per site. With Extracto you describe what each field means once, in plain language, and the model locates it on whatever layout the page currently uses. The result is validated against the types you declared, so you get a number for price and rating without writing parsing or cleanup code.
Can I extract a whole course catalog with one call?
No, and that is intentional. Extracto takes one URL per request and returns the structured data for that single course page; it is not a crawler that follows links across a catalog. If you want many courses, you collect the individual course URLs yourself (from a sitemap, a category listing you already have, or your own database) and call the API once per URL. This keeps each extraction predictable and your request volume modest and easy to reason about, which is also the responsible way to interact with any site's Terms of Service and robots.txt.