# Udemy Course Scraper (`khadinakbar/udemy-course-scraper`) Actor

Scrape Udemy courses by keyword search or course URL — price, rating, reviews, enrollment, instructor, level, language. MCP/API-ready.

- **URL**: https://apify.com/khadinakbar/udemy-course-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Developer tools, MCP servers, Lead generation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 course scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Udemy Course Scraper

Udemy Course Scraper collects Udemy course data from either keyword searches or direct course URLs and returns one flat record per course. It accepts search queries such as a topic phrase, or full Udemy course landing-page URLs, and each returned record can include fields such as title, URL, headline, price, rating, review count, enrollment, lecture count, level, category, language, instructor details, and objectives. The outcome is a structured dataset that is ready for analysis, enrichment, or agent workflows through Apify and Apify MCP.

### Best fit and connected workflows

This Actor fits workflows that start with a topic or a specific course page and end with structured course records.

Common routing patterns include:

- Keyword research for a topic, followed by filtering on rating, reviews, level, or language.
- Course URL enrichment, where a list of Udemy links becomes a detailed dataset.
- Market scanning for course pricing, instructor positioning, and catalog coverage.
- AI agent workflows through Apify MCP, where an agent needs compact course facts instead of browsing pages manually.

### Focused standalone workflow

This Actor is designed as a focused standalone workflow.

### Practical scenario

Maya is building a spreadsheet of Udemy courses for a Python learning page. She starts with the keyword `python for beginners` and leaves the course URL field empty. The Actor returns records with `title`, `price`, `rating`, `numReviews`, `numSubscribers`, `level`, `language`, and `url`. Maya uses those fields to compare course positioning and then opens the most relevant course URLs for a deeper review.

### Input

Use keyword search, course URLs, or both.

| Field | Type | Purpose |
|---|---|---|
| `searchQueries` | array of strings | Keyword searches against the Udemy catalog. One record is returned per matching course. Each query is paginated up to `maxResults`. |
| `startUrls` | array of strings | Full Udemy course landing-page URLs for detailed scraping. Each URL returns one deep record. |
| `maxResults` | integer | Maximum number of courses returned per search query. Applies to search queries only. |
| `language` | string | Filters search results by Udemy course language ISO code such as `en`, `es`, or `de`. Applies to search queries only. |
| `sortBy` | string | Search ordering: `relevance`, `highest-rated`, `most-reviewed`, or `newest`. Applies to search queries only. |
| `proxyConfiguration` | object | Proxy settings. The default uses Apify Residential US. |

Valid focused input example:

```json
{
  "searchQueries": [
    "excel"
  ],
  "startUrls": [
    "https://www.udemy.com/course/the-complete-javascript-course/"
  ],
  "maxResults": 25,
  "language": "en",
  "sortBy": "highest-rated"
}
```

### Output

The Actor stores scraped course records in a dataset. The dataset item fields are defined by the live output contract.

| Field | Type | Meaning |
|---|---|---|
| `courseId` | integer | Udemy numeric course ID |
| `title` | string | Course title |
| `url` | string | Course landing-page URL |
| `headline` | string | Short course headline |
| `isPaid` | boolean | Paid or free course flag |
| `price` | string | Listed price text |
| `priceCurrency` | string | Price currency code |
| `numSubscribers` | integer | Enrolled students |
| `rating` | number | Average course rating |
| `numReviews` | integer | Review count |
| `numPublishedLectures` | integer | Published lecture count |
| `contentInfo` | string | Total content length |
| `level` | string | Course level |
| `category` | string | Udemy category |
| `subcategory` | string | Udemy subcategory |
| `language` | string | Course language |
| `lastUpdated` | string | Last update date text |
| `createdAt` | string | Creation date text |
| `instructorName` | string | Lead instructor name |
| `instructorJobTitle` | string | Instructor job title |
| `instructorUrl` | string | Instructor page URL |
| `imageUrl` | string | Course image URL |
| `objectives` | array of strings | "What you'll learn" items |
| `searchQuery` | string | Search query that produced the record |
| `_source` | string | Source indicator |

Illustrative dataset record:

```json
{
  "courseId": 123456,
  "title": "Complete Python Bootcamp",
  "url": "https://www.udemy.com/course/complete-python-bootcamp/",
  "headline": "Learn Python from scratch",
  "isPaid": true,
  "price": "$19.99",
  "priceCurrency": "USD",
  "numSubscribers": 120000,
  "rating": 4.6,
  "numReviews": 34000,
  "numPublishedLectures": 220,
  "contentInfo": "42 total hours",
  "level": "Beginner",
  "category": "Development",
  "subcategory": "Programming Languages",
  "language": "en",
  "lastUpdated": "2025",
  "createdAt": "2019",
  "instructorName": "Jane Instructor",
  "instructorJobTitle": "Software Engineer",
  "instructorUrl": "https://www.udemy.com/user/jane-instructor/",
  "imageUrl": "https://img-c.udemycdn.com/course/750x422/123456.jpg",
  "objectives": [
    "Build Python scripts",
    "Work with data structures"
  ],
  "searchQuery": "python for beginners",
  "_source": "search"
}
```

### How it works

The Actor uses Apify Residential US by default. The live contract shows an impit Chrome-TLS approach, Udemy api-2.0 access, and a landing-page `ld+json` fallback for course-detail-by-URL. The contract also includes soft-fail validation, honest-fail anti-bot handling, cost-cap logging, and safe dataset writes.

### Pricing

This Actor uses Pay per event pricing, plus standard Apify platform usage. The primary billed event is `Course scraped`, which is charged once for each returned course record, whether it comes from a search result or a course URL. There is also an `Actor start` event that applies once per run.

A simple example: if you run a search that returns fifty courses, the billing includes one run start event and fifty course-scraped events. For current rates and any platform usage details, check the live Pricing tab in Apify Console before you run the Actor.

### Use with AI agents (MCP)

This Actor is available as an Apify Actor usable through Apify MCP. It is designed for agents that need structured Udemy course facts from a single tool call.

Tool description: scrape Udemy courses by keyword search or course URL and return one dataset record per course, including pricing, popularity, instructor, and taxonomy fields.

Exact Actor identity: `khadinakbar/udemy-course-scraper`

Example agent prompt:

> Find Udemy courses for "excel" in English, sort by highest-rated, and return the top records with title, price, rating, reviews, students, level, language, and URL.

Output interpretation:

- Search mode returns one record per matching course.
- URL mode returns one deep record per supplied course URL.
- The dataset contains the authoritative scraped items, and the `courses` output points to the default dataset items endpoint.
- Use `searchQuery` to trace which keyword produced a record.
- Use `url` and `instructorUrl` as provenance links for review and follow-up.
- Pagination applies to keyword searches through `maxResults`.
- Cost scales with the number of returned course records, so larger result sets produce more billed events.

### Example: run via Apify API and read the dataset

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

const client = new ApifyClient({
  token: process.env.APIFY_TOKEN,
});

const input = {
  searchQueries: ['python for beginners'],
  maxResults: 10,
  sortBy: 'highest-rated',
  language: 'en',
};

const run = await client.actor('khadinakbar/udemy-course-scraper').call(input);

const { items } = await client.dataset(run.defaultDatasetId).listItems();

console.log(items);
```

### Best results and outcome guidance

Use keyword searches when you want market coverage, then narrow the result set with `language` and `sortBy`. Use direct course URLs when you already have a shortlist and want a deeper record for each course. Keep search terms specific to the topic you want to study, because each query is paginated independently up to `maxResults`. For agent workflows, pass only one task at a time so the returned dataset stays easy to interpret.

### Design note

I found that the live dataset contract exposes a compact, flat record shape with both discovery fields, such as `searchQuery`, and detail fields, such as `instructorUrl`, which makes it straightforward to use the same Actor for catalog research and URL-based enrichment.

### FAQ

#### When should I use `searchQueries` instead of `startUrls`?

Use `searchQueries` when you want Udemy catalog discovery from a topic phrase. Use `startUrls` when you already have the exact course landing pages and want detailed records for those pages.

#### Can I combine keyword search and course URLs in one run?

Yes. The input schema allows both. Search queries return paginated results, and course URLs return one deep record per URL.

#### How do I narrow results to one language?

Set `language` to an ISO code such as `en`, `es`, or `de`. That filter applies to keyword searches.

#### Which sort order should I use for discovery work?

`highest-rated` is useful when you want top-rated courses first. `most-reviewed` is useful when you want higher-volume results. `newest` surfaces recent courses. `relevance` follows the default Udemy search order.

#### What dataset fields are most useful for comparisons?

Common comparison fields are `price`, `rating`, `numReviews`, `numSubscribers`, `level`, `language`, and `instructorName`.

### Responsible use

Use this Actor for research, analysis, enrichment, and other lawful workflows. Review the source site's terms and your own compliance requirements before storing or redistributing data.

# Actor input Schema

## `searchQueries` (type: `array`):

Keyword searches run against the Udemy catalog, one record per matching course (e.g. 'python for beginners', 'excel'). Each query is paginated up to maxResults. Leave empty if you only want to scrape specific course URLs. NOT a course URL — put full course links in 'Course URLs' instead.

## `startUrls` (type: `array`):

Full Udemy course landing-page URLs to scrape in detail (e.g. 'https://www.udemy.com/course/the-complete-javascript-course/'). Each returns one deep record. Leave empty if you only want keyword search. NOT a search keyword — use 'Search queries' for that.

## `maxResults` (type: `integer`):

Maximum number of courses to return per search query (course URLs are always all scraped). Defaults to 50. Range 1-1000. Higher values cost more and run longer at $0.003 per course returned.

## `language` (type: `string`):

Restrict search results to courses in a single language by ISO code (e.g. 'en', 'es', 'de'). Applies only to search queries, not course URLs. Leave empty for all languages. NOT a country code — it filters course content language.

## `sortBy` (type: `string`):

Order of search results. 'relevance' is Udemy default; 'highest-rated' surfaces top-rated courses; 'most-reviewed' surfaces popular ones; 'newest' surfaces recent ones. Applies only to search queries.

## `proxyConfiguration` (type: `object`):

Proxy settings. Udemy requires Apify Residential US to pass Cloudflare and the api-2.0 IP gate — this is the enforced default. Override only if you know what you are doing.

## Actor input object example

```json
{
  "searchQueries": [
    "excel",
    "digital marketing"
  ],
  "startUrls": [
    "https://www.udemy.com/course/the-complete-javascript-course/"
  ],
  "maxResults": 50,
  "language": "en",
  "sortBy": "relevance",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `courses` (type: `string`):

All scraped Udemy course records.

# 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 = {
    "searchQueries": [
        "python for beginners"
    ],
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/udemy-course-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 = {
    "searchQueries": ["python for beginners"],
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

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

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

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

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "python for beginners"
  ],
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call khadinakbar/udemy-course-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/udemy-course-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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