# Udemy Course Catalog & Pricing Data Scraper (`datascraperes/udemy-course-catalog-scraper`) Actor

Search public Udemy courses by keyword or phrase and return a deduplicated catalog with titles, ratings, prices, instructors, outcomes, badges, images and curriculum counts. Optionally filter free courses or enrich records with public course-page details.

- **URL**: https://apify.com/datascraperes/udemy-course-catalog-scraper.md
- **Developed by:** [DataScraperES](https://apify.com/datascraperes) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 udemy course results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**Udemy Course Catalog & Pricing Data Scraper** turns keywords and phrases such as `python` or `data science` into a clean Dataset of unique public Udemy courses. It returns course metadata, ratings, instructors, learning outcomes, curriculum counts, images and public price snapshots, with optional course-page details.

### What this Actor does

The Actor searches the public Udemy course catalog from the terms you enter, follows pagination until the requested number of unique courses is reached or the source is exhausted, and writes one normalized Dataset item per course. It deduplicates courses across multiple terms and preserves the generated public search context in `sourceSearchUrl` and `page` for traceability.

You can also enable `freeOnly` to search for courses marked as free by the public catalog. The catalog filters support fixed Udemy-compatible selectors for `sortOrder` (`RELEVANCE`, `REVIEWS`, `RATING` or `TIME`), course languages, levels and video lengths, plus `minRating`, caption languages and optional requirements for closed captions, quizzes, coding exercises, practice tests, workspaces, roleplays, certification preparation or practice-test-only courses. Optional course-page enrichment adds structured fields such as description, publication date, language, offers, syllabus sections and audience information when those fields are available.

### Use cases

- Build course catalogs for education, training and competitor research.
- Compare course coverage, ratings, duration, instructors and public prices for several topics.
- Discover learning outcomes, images and curriculum counts for SEO or content planning.
- Monitor public Udemy search terms and export the results for downstream analysis.

### How to use

1. Open the Actor in Apify Console.
2. Enter one or more keywords or phrases in **What do you want to search for?**.
3. Set the maximum number of unique courses, then choose any catalog filters you need. The Udemy catalog filters are dropdowns or multiselects with predefined valid values, so you do not need to type filter codes. You can optionally select **Only free courses** or enable course-page details.
4. Click **Start** and open the Dataset when the run finishes.

### Input

`searchTerms` is required and accepts 1–10 unique keywords or phrases, each up to 200 characters. The Actor creates the Udemy search requests internally, so users do not need to construct URLs or query parameters. Terms are whitespace-normalized and duplicate terms are removed case-insensitively.

`maxItems` defaults to 100 and accepts 1–10,000 unique courses across all terms. `freeOnly` defaults to `false` and restricts the public search to courses marked free when enabled. `includeCourseDetails` defaults to `false`; enabling it makes an additional public course-page request for each returned course and can increase run time.

`sortOrder` defaults to `RELEVANCE`; use the predefined `REVIEWS`, `RATING` or `TIME` options for other supported catalog orderings. In the Apify UI, `languages` and `closedCaptionLanguages` are multiselects showing readable language names together with their ISO-639-1 codes, while `levels` and `videoLengths` expose the supported Udemy values as multiselects. API and JSON callers must still send the exact codes and enum values shown in the schema. `minRating` accepts 0–5 in half-point increments, and the feature flags are optional booleans that default to `false`.

#### Input fields

| Input | Apify control | JSON/API value | Default and limits |
| --- | --- | --- | --- |
| `searchTerms` | Keyword list | Array of keywords or phrases | Required; 1–10 unique terms, maximum 200 characters each. |
| `maxItems` | Number | Integer | `100`; from 1 to 10,000 unique courses. |
| `freeOnly` | Checkbox | Boolean | `false`; only free courses when enabled. |
| `sortOrder` | Dropdown | `RELEVANCE`, `REVIEWS`, `RATING` or `TIME` | `RELEVANCE`. The UI shows readable labels such as “Highest rating”. |
| `languages` | Multiselect | ISO-639-1 codes such as `EN` or `ES` | Empty; up to 10 languages. The UI shows labels such as “English (EN)” and “Spanish (ES)”. |
| `levels` | Multiselect | `ALL_LEVELS`, `BEGINNER`, `INTERMEDIATE` or `EXPERT` | Empty; up to 10 values. |
| `minRating` | Number | `0` to `5` | Empty; half-point increments only, for example `4.5`. |
| `videoLengths` | Multiselect | `EXTRA_SHORT`, `SHORT`, `MEDIUM`, `LONG` or `EXTRA_LONG` | Empty; up to 10 values. |
| `closedCaptionLanguages` | Multiselect | ISO-639-1 codes such as `EN` or `ES` | Empty; up to 10 languages. The UI shows the language name and code. |
| `mustHaveClosedCaptions` | Checkbox | Boolean | `false`. |
| `mustHaveQuizzes` | Checkbox | Boolean | `false`. |
| `mustHaveCodingExercises` | Checkbox | Boolean | `false`. |
| `mustHavePracticeTests` | Checkbox | Boolean | `false`. |
| `mustHaveWorkspaces` | Checkbox | Boolean | `false`. |
| `mustHaveRoleplays` | Checkbox | Boolean | `false`. |
| `practiceTestCoursesOnly` | Checkbox | Boolean | `false`. |
| `certificationPrepOnly` | Checkbox | Boolean | `false`. |
| `includeCourseDetails` | Checkbox | Boolean | `false`; requests optional public course-page details. |

The Apify interface prevents invalid values for selector-based filters before the run starts. JSON and API users should use the exact machine values in the third column; labels such as “English (EN)” are only the display text.

#### Quick start input

```json
{
  "searchTerms": [
    "python"
  ],
  "maxItems": 3,
  "freeOnly": false,
  "includeCourseDetails": false
}
```

#### Complete input example (all filters)

The following valid JSON includes every public input property. Empty selector arrays and `false` flags leave those optional filters disabled; use the predefined values from the table when you want to narrow the catalog.

```json
{
  "searchTerms": [
    "python"
  ],
  "maxItems": 3,
  "freeOnly": false,
  "sortOrder": "RELEVANCE",
  "languages": [],
  "levels": [],
  "minRating": 0,
  "videoLengths": [],
  "closedCaptionLanguages": [],
  "mustHaveClosedCaptions": false,
  "mustHaveQuizzes": false,
  "mustHaveCodingExercises": false,
  "mustHavePracticeTests": false,
  "mustHaveWorkspaces": false,
  "mustHaveRoleplays": false,
  "practiceTestCoursesOnly": false,
  "certificationPrepOnly": false,
  "includeCourseDetails": false
}
```

### Output

The default Dataset contains one item per unique public course. Items include the course ID, title, headline, URL, free-course and practice-test flags, locale, level, rating, review count, duration, lecture and practice-test counts, instructors, learning outcomes, badges, image URLs, update date, public price and capture timestamp. Some catalog values are nullable because Udemy does not publish every field for every course; the `price` key is retained and can be `null` when no public price snapshot is available. Optional detail fields are added only when requested and available.

This is the complete Dataset item from a real successful run:

```json
{
  "recordType": "course",
  "sourceSearchUrl": "https://www.udemy.com/courses/search/?src=ukw&q=python",
  "page": 0,
  "courseId": "2776760",
  "title": "100 Days of Code™: The Complete Python Pro Bootcamp",
  "headline": "Master Python by building 100 projects in 100 days. Learn data science, automation, build websites, games and apps!",
  "url": "https://www.udemy.com/course/100-days-of-code",
  "isFree": false,
  "isPracticeTestCourse": false,
  "locale": "en-US",
  "level": "ALL_LEVELS",
  "ratingAverage": 4.671892166137695,
  "ratingCount": 436596,
  "durationSeconds": 204491,
  "lectureCount": 604,
  "practiceTestQuestionsCount": 0,
  "instructors": [
    {
      "id": "31334738",
      "name": "Dr. Angela Yu, Developer and Lead Instructor"
    }
  ],
  "learningOutcomes": [
    "You will master the Python programming language by building 100 unique projects over 100 days.",
    "You will learn automation, game, app and web development, data science and machine learning all using Python.",
    "You will be able to program in Python professionally",
    "You will learn Selenium, Beautiful Soup, Request, Flask, Pandas, NumPy, Scikit Learn, Plotly, and Matplotlib.",
    "Create a portfolio of 100 Python projects to apply for developer jobs",
    "Be able to build fully fledged websites and web apps with Python",
    "Be able to use Python for data science and machine learning",
    "Build games like Blackjack, Pong and Snake using Python",
    "Build GUIs and Desktop applications with Python"
  ],
  "badges": [
    {
      "__typename": "BestSellerSubcategoryTopicBadge",
      "name": "Bestseller"
    },
    {
      "__typename": "BestSellerCategoryTopicBadge",
      "name": "Bestseller"
    },
    {
      "__typename": "BestSellerSubcategoryBadge",
      "name": "Bestseller"
    }
  ],
  "images": {
    "height125": "https://img-c.udemycdn.com/course/125_H/2776760_f176_10.jpg",
    "px100x100": "https://img-c.udemycdn.com/course/100x100/2776760_f176_10.jpg",
    "px240x135": "https://img-c.udemycdn.com/course/240x135/2776760_f176_10.jpg",
    "px304x171": "https://img-c.udemycdn.com/course/304x171/2776760_f176_10.jpg",
    "px480x270": "https://img-c.udemycdn.com/course/480x270/2776760_f176_10.jpg",
    "px50x50": "https://img-c.udemycdn.com/course/50x50/2776760_f176_10.jpg"
  },
  "updatedOn": "2026-09-15",
  "price": {
    "amount": 24.99,
    "currency": "GBP",
    "priceString": "£24.99",
    "listAmount": 34.99,
    "discountAmount": 25.0
  },
  "scrapedAt": "2026-09-24T09:00:03.915968+00:00"
}
```

Use the Dataset export controls in Apify to download JSON, CSV or spreadsheet-compatible files. Run statistics are available separately in the Actor's `RUN_STATS` key-value record.

### Pricing

This Actor uses Apify pay-per-event pricing. One unique public course successfully written to the default Dataset creates one `course-result` event. The equivalent prices per 1,000 delivered courses are:

| Apify tier | Price per course | Equivalent per 1,000 |
|---|---:|---:|
| FREE | $0.00100 | $1.00 |
| BRONZE | $0.00090 | $0.90 |
| SILVER | $0.00080 | $0.80 |
| GOLD | $0.00075 | $0.75 |
| PLATINUM | $0.00075 | $0.75 |
| DIAMOND | $0.00075 | $0.75 |

PLATINUM and DIAMOND intentionally use the same per-result rate as GOLD in this pricing ladder. Failed requests, empty responses, duplicate courses and records that are not written to the Dataset do not create a `course-result` charge. The active billing contract and any standard Apify usage treatment are shown in the Actor's **Pricing** tab.

### Related Actors

| Actor | Best for |
|---|---|
| [Keyword Research & SERP Data](https://apify.com/datascraperes/keyword-research-serp) | Finding demand, related queries and topic opportunities before comparing Udemy course coverage. |

### Limits and data quality

The Actor accepts up to 10 search terms and returns up to 10,000 unique courses per run. The maximum is a unique-course limit across all terms, not a page limit. If the public catalog has fewer results than requested, the Dataset contains the available results and `RUN_STATS.sourceExhausted` indicates that pagination ended before the requested maximum.

Prices and promotional offers are market- and time-sensitive snapshots. Ratings, counts, curriculum values, images and learning outcomes depend on what Udemy returns for each public course at run time. Optional course-page fields can be unavailable; the item remains usable and reports `detailStatus: "not_available"` when enrichment cannot provide them.

The Actor uses bounded recovery for transient failures and stops with an explicit run error when the public source returns an incomplete catalog or access challenge. It does not claim `Completed` for a silently truncated primary catalog.

### Frequently asked questions

#### Can I search several topics in one run?

Yes. Add up to 10 keywords or phrases to `searchTerms`. Results are deduplicated by course ID across all terms, and each item retains the generated public search context.

#### Can I retrieve only free courses?

Yes. Set `freeOnly` to `true`. This applies the public free-course filter internally without requiring you to know Udemy query parameters.

#### What happens when course-page details are unavailable?

The primary catalog item is retained. With `includeCourseDetails` enabled, the item receives `detailStatus: "not_available"` when the optional page cannot provide structured details.

### Responsible use

Use this Actor only for lawful research and automation of publicly available course information. You are responsible for respecting Udemy's terms, applicable privacy and data-protection rules, intellectual-property rights and any restrictions that apply to your intended use. Do not use it to access private accounts, enrolled content or protected lesson material.

### Support

Open the Actor's **Issues** tab with the run ID, exact input and a concise description of the expected versus actual result. Do not include credentials or private account data in a support request.

For Python, JavaScript and cURL integration examples, see the [public integration repository](https://github.com/datacrawler-edu/udemy-course-catalog-python).

# Actor input Schema

## `searchTerms` (type: `array`):

Enter one or more keywords or phrases, such as python or data science. The Actor creates the Udemy search requests internally.

## `maxItems` (type: `integer`):

Maximum number of unique courses written across all search terms. Pagination continues until this number is reached or Udemy is exhausted.

## `freeOnly` (type: `boolean`):

Limit the catalog to courses marked as free by the public Udemy search service.

## `sortOrder` (type: `string`):

Order results by relevance, review count, rating, or newest update.

## `languages` (type: `array`):

Optional course languages. Select one or more ISO-639-1 languages from the list.

## `levels` (type: `array`):

Optional Udemy levels. Select one or more predefined levels.

## `minRating` (type: `number`):

Optional minimum average rating from 0 to 5, in half-point increments.

## `videoLengths` (type: `array`):

Optional Udemy video-length bands. Select one or more predefined ranges.

## `closedCaptionLanguages` (type: `array`):

Optional closed-caption languages. Select one or more ISO-639-1 languages from the list.

## `mustHaveClosedCaptions` (type: `boolean`):

Only return courses with closed captions.

## `mustHaveQuizzes` (type: `boolean`):

Only return courses with quizzes.

## `mustHaveCodingExercises` (type: `boolean`):

Only return courses with coding exercises.

## `mustHavePracticeTests` (type: `boolean`):

Only return courses with practice tests.

## `mustHaveWorkspaces` (type: `boolean`):

Only return courses with workspaces.

## `mustHaveRoleplays` (type: `boolean`):

Only return courses with roleplay activities.

## `practiceTestCoursesOnly` (type: `boolean`):

Only return courses flagged as practice-test courses.

## `certificationPrepOnly` (type: `boolean`):

Only return courses flagged as certification preparation.

## `includeCourseDetails` (type: `boolean`):

Fetch each public course page and include available JSON-LD detail fields. This increases request count and run time.

## Actor input object example

```json
{
  "searchTerms": [
    "python"
  ],
  "maxItems": 3,
  "freeOnly": false,
  "sortOrder": "RELEVANCE",
  "languages": [],
  "levels": [],
  "videoLengths": [],
  "closedCaptionLanguages": [],
  "mustHaveClosedCaptions": false,
  "mustHaveQuizzes": false,
  "mustHaveCodingExercises": false,
  "mustHavePracticeTests": false,
  "mustHaveWorkspaces": false,
  "mustHaveRoleplays": false,
  "practiceTestCoursesOnly": false,
  "certificationPrepOnly": false,
  "includeCourseDetails": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing one normalized item per unique public course.

## `runStats` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "python"
    ],
    "maxItems": 3,
    "freeOnly": false,
    "sortOrder": "RELEVANCE",
    "languages": [],
    "levels": [],
    "videoLengths": [],
    "closedCaptionLanguages": [],
    "mustHaveClosedCaptions": false,
    "mustHaveQuizzes": false,
    "mustHaveCodingExercises": false,
    "mustHavePracticeTests": false,
    "mustHaveWorkspaces": false,
    "mustHaveRoleplays": false,
    "practiceTestCoursesOnly": false,
    "certificationPrepOnly": false,
    "includeCourseDetails": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascraperes/udemy-course-catalog-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchTerms": ["python"],
    "maxItems": 3,
    "freeOnly": False,
    "sortOrder": "RELEVANCE",
    "languages": [],
    "levels": [],
    "videoLengths": [],
    "closedCaptionLanguages": [],
    "mustHaveClosedCaptions": False,
    "mustHaveQuizzes": False,
    "mustHaveCodingExercises": False,
    "mustHavePracticeTests": False,
    "mustHaveWorkspaces": False,
    "mustHaveRoleplays": False,
    "practiceTestCoursesOnly": False,
    "certificationPrepOnly": False,
    "includeCourseDetails": False,
}

# Run the Actor and wait for it to finish
run = client.actor("datascraperes/udemy-course-catalog-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "python"
  ],
  "maxItems": 3,
  "freeOnly": false,
  "sortOrder": "RELEVANCE",
  "languages": [],
  "levels": [],
  "videoLengths": [],
  "closedCaptionLanguages": [],
  "mustHaveClosedCaptions": false,
  "mustHaveQuizzes": false,
  "mustHaveCodingExercises": false,
  "mustHavePracticeTests": false,
  "mustHaveWorkspaces": false,
  "mustHaveRoleplays": false,
  "practiceTestCoursesOnly": false,
  "certificationPrepOnly": false,
  "includeCourseDetails": false
}' |
apify call datascraperes/udemy-course-catalog-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datascraperes/udemy-course-catalog-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/OdKs0a5TOlzXG1vjI/builds/D4HO3iaN8mscTDdqe/openapi.json
