# Coursera Courses Scraper (`devilscrapes/coursera-courses-scraper`) Actor

Search Coursera and export every course, specialization, and professional certificate result into clean dataset rows — partner university, star rating, review count, difficulty, duration, skills gained, and access tags. Devil Scrapes handles the fetching so your dataset stays clean.

- **URL**: https://apify.com/devilscrapes/coursera-courses-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## Coursera Courses Scraper

**💰 $5.20 / 1 000 results**  ·  pay only for results  ·  no credit card to try

*We do the dirty work so your dataset stays clean.* 😈

Search Coursera and export every course, specialization, and professional certificate result into clean dataset rows — partner university, star rating, review count, difficulty, duration, skills gained, and access tags.

</div>

***

### 🎯 What this scrapes

Point it at any Coursera search term — `python`, `machine learning`, `product management` — and it walks the public search results page, page by page, pulling every course, Specialization, Professional Certificate, and degree program that comes back. Each result becomes one dataset row with the partner university or company, star rating, review count, difficulty level, time commitment, the skills Coursera lists under "Skills you'll gain," and the access badges Coursera itself shows (Free trial, Build toward a degree, Job ready). We read Coursera's own server-rendered result cards rather than a JSON API that can be pulled out from under us without notice.

### 🔥 What we handle for you

- 🛡️ **Browser fingerprint rotation** — `curl-cffi` impersonates real Chrome / Firefox / Safari TLS handshakes so Coursera sees a browser, not Python.
- 🌐 **Apify Proxy on every request** — fresh session and exit IP whenever a fetch fails, no manual retry wiring required on your end.
- 🔁 **Retries with exponential backoff** on `408 / 429 / 5xx` — up to 5 attempts per page.
- 🧱 **Per-query fault isolation** — one query that fails to fetch never sinks the others; the run finishes and tells you exactly which term came up short.
- 🧊 **Clean, typed dataset rows** — Pydantic-validated, stable de-duplication across pages, JSON / CSV / Excel export straight from the Apify Console.
- 💰 **Pay-Per-Event pricing** — you only pay for results that hit your dataset. No data, no charge.

### 💡 Use cases

- **Corporate L\&D catalog research** — build a comparison sheet of every Coursera course/Specialization on a topic before recommending a learning path.
- **Course-creator competitive research** — see how competing courses in your niche are rated, priced (Free trial vs paid), and positioned before you launch your own.
- **EdTech market research** — track which partner universities and companies dominate a subject area, and how ratings/review volume shift over time.
- **Curriculum sourcing** — feed a clean, structured export into an internal tool that recommends courses by skill gap.

### ⚙️ How to use it

1. Click **Try for free** at the top of the page.
2. Enter one or more search queries and how many results you want per query.
3. Click **Start**. Output streams into the run's dataset as pages are fetched.
4. Export from **Storage → Dataset** as JSON, CSV, or Excel — or fetch via the API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `queries` | `array` | **yes** | \['python'] | Search terms to run against Coursera's public search, e.g. `python` or `machine learning`. |
| `maxResultsPerQuery` | `integer` | no | 24 | Stop paging a query once this many results have been emitted (1-120). Coursera's search page carries 12 results per page. |
| `proxyConfiguration` | `object` | no | {'useApifyProxy': True} | Apify Proxy configuration. Coursera's search page served cleanly on datacenter exits during recon — no residential group required. |

#### Example input

```json
{
  "queries": ["python", "data science"],
  "maxResultsPerQuery": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### 📤 Output

Every row is one search result.

| Field | Type | Notes |
|---|---|---|
| `query` | `string` | The search term that surfaced this result. |
| `title` | `string` | Course, Specialization, or Professional Certificate title. |
| `url` | `string` | Absolute Coursera URL for this result's detail page. |
| `partner` | `string` | Offering university or company, e.g. 'IBM'. Null if Coursera omits it. |
| `product_type` | `string` | `COURSE`, `SPECIALIZATION`, `PROFESSIONAL_CERTIFICATE`, `DEGREE`, or `OTHER`. |
| `difficulty_level` | `string` | e.g. 'Beginner', 'Intermediate'. Null when Coursera doesn't show one. |
| `duration` | `string` | e.g. '3 - 6 Months'. Null when Coursera doesn't show one. |
| `rating` | `number` | Average star rating (0-5) at scrape time. Null when there's no rating yet. |
| `rating_count` | `integer` | Number of reviews behind the rating — the closest public popularity signal Coursera exposes; not a verified enrollment count. |
| `skills` | `array` | Skills Coursera lists under "Skills you'll gain." |
| `access_tags` | `array` | Coursera's own badges, e.g. `Free trial`, `Build toward a degree`, `Job ready` — the closest public price-tier / positioning signal on the search page. |
| `object_id` | `string` | Coursera's internal search-result object ID, when present. |

#### Example output

```json
{
  "query": "python",
  "title": "Python for Everybody",
  "url": "https://www.coursera.org/specializations/python",
  "partner": "University of Michigan",
  "product_type": "SPECIALIZATION",
  "difficulty_level": "Beginner",
  "duration": "3 - 6 Months",
  "rating": 4.8,
  "rating_count": 281000,
  "skills": ["Database Design", "Data Processing", "Web Scraping", "SQL"],
  "access_tags": ["Free trial", "Build toward a degree"],
  "object_id": "s12n~F-h1g0w7EeWeOApO_l5R1w"
}
```

### 💰 Pricing

Pay-Per-Event — you pay only when these events fire:

| Event | USD | What it is |
|---|---:|---|
| `actor-start` | $0.20 | One-off warm-up charge per run |
| `result-scraped` | $0.005 | Charged once per course/specialization/certificate row written |

Example: 1 000 results at the rates above ≈ **$5.20**. No subscription, no minimum, no card to start — Apify gives every new account free credit.

### 🚧 Limitations

Public search results only — no login, no enrolled-learner data, no course-content scraping. `rating_count` reflects Coursera's own review count, not a verified enrollment figure — we don't fabricate an enrollment number Coursera doesn't publish. Coursera's search treats unmatched or gibberish queries as an opportunity to show generic recommendations rather than a true empty state, so an unusual query still returns rows — that's Coursera's own behavior, not a bug in this Actor.

### ❓ FAQ

**Why don't you report a "no matches" state?**

Coursera's own search never returns a hard zero — even a nonsense query gets back a page of recommended courses. We pass through exactly what Coursera serves rather than inventing a "no results" signal it doesn't have.

**Is `rating_count` the same as enrollment count?**

No. Coursera's search cards expose a star rating and the review count behind it — we report that number honestly as `rating_count` rather than relabeling it "enrollments," which Coursera does not publish on this page.

**Does this tell me the price of a course?**

Coursera's search page doesn't show a dollar price — most content is bundled under a Coursera Plus subscription or a "Free trial" window. We surface the `access_tags` badges Coursera itself displays (Free trial, Build toward a degree, Job ready) as the closest public price-tier signal.

**What happens if one query fails?**

That query is skipped and reported in the run's final status message; every other query in the same run still completes.

**Can I get results for a specific university, like only Google or IBM courses?**

Not directly — filter the `partner` field in the output. Coursera's search UI supports partner filters, but they're applied client-side after the initial page load, not via a documented URL parameter we could pass through.

### 💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an
issue on the Actor's **Issues** tab on Apify Console — we ship
fixes weekly and we read every report.

***

<div align="center">

Built by **[Devil Scrapes](https://apify.com/DevilScrapes)** 😈 — a small fleet of
opinionated public-data Actors. Honest pricing, real engineering, zero fine print.

</div>

# Actor input Schema

## `queries` (type: `array`):

Search terms to run against Coursera's public search, e.g. <code>python</code> or <code>machine learning</code>.

## `maxResultsPerQuery` (type: `integer`):

Stop paging a query once this many results have been emitted (1-120). Coursera's search page carries 12 results per page, so anything above 12 pages a second request.

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

Apify Proxy configuration. Coursera's search page served cleanly on datacenter exits during recon — no residential group required.

## Actor input object example

```json
{
  "queries": [
    "python",
    "data science"
  ],
  "maxResultsPerQuery": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "queries": [
        "python",
        "data science"
    ],
    "maxResultsPerQuery": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/coursera-courses-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 = {
    "queries": [
        "python",
        "data science",
    ],
    "maxResultsPerQuery": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/coursera-courses-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 '{
  "queries": [
    "python",
    "data science"
  ],
  "maxResultsPerQuery": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/coursera-courses-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/coursera-courses-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/aLm93c6IDoAb8zzn8/builds/YyAAaPPWDyMtHS6p1/openapi.json
