{
  "data": {
    "id": "iQnLqjCqc174ezrSc",
    "actId": "HkEpjBr9pdGuzJZQF",
    "userId": "IYgBDiXtHOijAaUel",
    "startedAt": "2026-11-11T18:42:11.760Z",
    "finishedAt": "2026-11-11T18:42:22.733Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 10906,
      "runTimeSecs": 10.906,
      "computeUnits": 0.012117777777777778,
      "imageSizeBytes": 319180800
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "QYo53EZkJk0prePWY",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"LinkedIn Learning Catalog Input\",\n  \"description\": \"Search the public LinkedIn Learning catalog by keyword, filter by level, type, length, software and sort order, or read specific course, learning-path and chapter URLs. No login or cookie is required.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"mode\": {\n      \"title\": \"Mode\",\n      \"type\": \"string\",\n      \"description\": \"What to collect. 'Search the catalog' needs searchQuery. 'Read specific URLs' needs urls. 'Browse learning paths' reads the public all-paths page.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"search\",\n        \"byUrls\",\n        \"learningPaths\"\n      ],\n      \"enumTitles\": [\n        \"Search the catalog\",\n        \"Read specific LinkedIn Learning URLs\",\n        \"Browse all learning paths\"\n      ],\n      \"default\": \"search\",\n      \"prefill\": \"search\"\n    },\n    \"searchQuery\": {\n      \"title\": \"Search query\",\n      \"type\": \"string\",\n      \"description\": \"Keyword or skill to search for, e.g. 'Python machine learning' or 'project management'. Put one query per line to run several searches in one run; each line is labelled in the output.\",\n      \"editor\": \"textfield\",\n      \"prefill\": \"Python machine learning\"\n    },\n    \"urls\": {\n      \"title\": \"LinkedIn Learning URLs\",\n      \"type\": \"array\",\n      \"description\": \"Course, learning-path, chapter/lesson, topic or filtered search URLs. Used only in 'Read specific LinkedIn Learning URLs' mode.\",\n      \"editor\": \"requestListSources\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"url\": {\n            \"title\": \"URL\",\n            \"type\": \"string\",\n            \"description\": \"LinkedIn Learning course, learning-path, chapter/lesson, topic or filtered search URL.\"\n          }\n        }\n      },\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"maxResults\": {\n      \"title\": \"Max results per query\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum records per query (or per URL list in URL mode). LinkedIn's guest catalog exposes at most 50 cards per filter slice; the actor re-runs the query across its own filters to collect more.\",\n      \"editor\": \"number\",\n      \"minimum\": 1,\n      \"maximum\": 500,\n      \"default\": 50,\n      \"prefill\": 3\n    },\n    \"difficultyLevel\": {\n      \"title\": \"Difficulty level\",\n      \"type\": \"string\",\n      \"description\": \"Filter by skill level. 'All levels' returns every level.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"\",\n        \"BEGINNER\",\n        \"INTERMEDIATE\",\n        \"ADVANCED\"\n      ],\n      \"enumTitles\": [\n        \"All levels\",\n        \"Beginner\",\n        \"Intermediate\",\n        \"Advanced\"\n      ],\n      \"default\": \"\",\n      \"prefill\": \"\",\n      \"sectionCaption\": \"Search filters\",\n      \"sectionDescription\": \"Server-side filters from LinkedIn Learning's own catalog. They apply only in search mode (and to search URLs in URL mode).\"\n    },\n    \"assetType\": {\n      \"title\": \"Asset type\",\n      \"type\": \"string\",\n      \"description\": \"Kind of learning content. 'All types' mixes courses, learning paths and videos.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"COURSE\",\n        \"LEARNING_PATH\",\n        \"VIDEO\",\n        \"ALL\"\n      ],\n      \"enumTitles\": [\n        \"Course\",\n        \"Learning path\",\n        \"Video (chapter)\",\n        \"All types\"\n      ],\n      \"default\": \"COURSE\",\n      \"prefill\": \"COURSE\"\n    },\n    \"sortBy\": {\n      \"title\": \"Sort by\",\n      \"type\": \"string\",\n      \"description\": \"Order of the results: LinkedIn's best match, view count, or newest release.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"RELEVANCE\",\n        \"POPULARITY\",\n        \"RECENCY\"\n      ],\n      \"enumTitles\": [\n        \"Best match\",\n        \"Most viewed\",\n        \"Newest\"\n      ],\n      \"default\": \"RELEVANCE\",\n      \"prefill\": \"RELEVANCE\"\n    },\n    \"duration\": {\n      \"title\": \"Time to complete\",\n      \"type\": \"string\",\n      \"description\": \"Filter by total course length. 'Any length' returns every length.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"\",\n        \"BETWEEN_0_TO_10_MIN\",\n        \"BETWEEN_10_TO_30_MIN\",\n        \"BETWEEN_30_TO_60_MIN\",\n        \"BETWEEN_1_TO_2_HOURS\",\n        \"BETWEEN_2_TO_3_HOURS\",\n        \"MORE_THAN_3_HOURS\"\n      ],\n      \"enumTitles\": [\n        \"Any length\",\n        \"Under 10 minutes\",\n        \"10-30 minutes\",\n        \"30-60 minutes\",\n        \"1-2 hours\",\n        \"2-3 hours\",\n        \"3+ hours\"\n      ],\n      \"default\": \"\",\n      \"prefill\": \"\"\n    },\n    \"software\": {\n      \"title\": \"Software\",\n      \"type\": \"string\",\n      \"description\": \"Keep only content that teaches this LinkedIn Learning software label, e.g. 'Python', 'Microsoft Excel', 'SQL' or 'ChatGPT'. LinkedIn applies only one software label per request.\",\n      \"editor\": \"textfield\"\n    },\n    \"topic\": {\n      \"title\": \"Extra keywords\",\n      \"type\": \"string\",\n      \"description\": \"Optional words appended to every search query to narrow it, e.g. 'AWS' or 'for beginners'.\",\n      \"editor\": \"textfield\"\n    },\n    \"includeDetails\": {\n      \"title\": \"Include full course details\",\n      \"type\": \"boolean\",\n      \"description\": \"Open each record's public page for description, skills, syllabus, chapters, free-preview flags, reviews, rating, learner count, provider and certificate. Turn off for a faster, cheaper catalog snapshot.\",\n      \"editor\": \"checkbox\",\n      \"default\": true,\n      \"prefill\": false,\n      \"sectionCaption\": \"Output and connection\",\n      \"sectionDescription\": \"Detail enrichment and optional connection settings.\"\n    },\n    \"proxyConfiguration\": {\n      \"title\": \"Proxy configuration\",\n      \"type\": \"object\",\n      \"description\": \"Optional. The actor connects directly by default and only escalates to a datacenter proxy if LinkedIn blocks a request. Change this only if you need a specific proxy setup.\",\n      \"editor\": \"proxy\",\n      \"prefill\": {\n        \"useApifyProxy\": false\n      },\n      \"default\": {\n        \"useApifyProxy\": false\n      }\n    }\n  },\n  \"required\": [\n    \"mode\"\n  ]\n}",
    "readme": "# LinkedIn Learning Course & Learning Path Finder\n\nRead the public LinkedIn Learning catalog without an account, a subscription seat or a cookie. Search by keyword with LinkedIn's own filters, read specific course / learning-path / chapter URLs, or browse every learning path, and get structured records with instructor, duration, level, rating, learner count, skills, syllabus, reviews and certificate data.\n\n## What this actor does\n\n- **Searches the public catalog** by keyword, with one query per line for batch runs.\n- **Uses LinkedIn's real filters**: skill level, content type, time to complete, software label and sort order (best match, most viewed, newest).\n- **Collects past the 50-card guest page** by re-running the query across LinkedIn's own filter slices and merging unique records.\n- **Reads detail pages** for the full record: description, skills taught, syllabus sections, chapters, free-preview lessons, rating, rating count, learner count, provider, category path, reviews and certificate.\n- **Accepts URLs**: individual courses, learning paths, video chapters, topic pages and filtered search URLs.\n- **Browses all learning paths** from the public all-paths page.\n- **Skips LinkedIn's no-results fallback.** When nothing matches, LinkedIn renders a page of unrelated popular courses; the actor detects that page and returns zero records with an explanation instead of fabricated relevance.\n- **Empty fields are omitted** instead of writing nulls or sentinels.\n\n## Modes\n\n| Mode | What it needs | What it returns |\n|---|---|---|\n| `search` (default) | `searchQuery` | Courses, learning paths or video chapters matching the query and filters |\n| `byUrls` | `urls` | One record per course, learning path, chapter or search URL |\n| `learningPaths` | nothing | Up to 50 public learning paths, optionally enriched |\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | select | `search` | `search`, `byUrls` or `learningPaths` |\n| `searchQuery` | text | - | Keyword or skill. One query per line for several searches; each record is labelled with the query that found it. Required in search mode. |\n| `urls` | URL list | - | Course, learning-path, chapter/lesson, topic or filtered search URLs. Required in URL mode. |\n| `maxResults` | integer | `50` | Records per query (or per URL list). `1`-`500`. |\n| `difficultyLevel` | select | all levels | `BEGINNER`, `INTERMEDIATE`, `ADVANCED` |\n| `assetType` | select | `COURSE` | `COURSE`, `LEARNING_PATH`, `VIDEO`, or `ALL` |\n| `sortBy` | select | `RELEVANCE` | `RELEVANCE`, `POPULARITY` (view count), `RECENCY` |\n| `duration` | select | any length | Under 10 min, 10-30 min, 30-60 min, 1-2 h, 2-3 h, 3+ h |\n| `software` | text | - | One LinkedIn software label, e.g. `Python`, `Microsoft Excel`, `SQL`, `ChatGPT` |\n| `topic` | text | - | Extra words appended to every query to narrow it |\n| `includeDetails` | boolean | `true` | Open each record's public page for the full detail surface. Turn off for a faster catalog snapshot. |\n| `proxyConfiguration` | proxy | direct | Optional override. The actor connects directly by default and only escalates to a datacenter proxy if LinkedIn blocks a request. |\n\n### Example: beginner Python courses, most viewed\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchQuery\": \"Python machine learning\",\n  \"difficultyLevel\": \"BEGINNER\",\n  \"assetType\": \"COURSE\",\n  \"sortBy\": \"POPULARITY\",\n  \"maxResults\": 100\n}\n```\n\n### Example: several skills in one run, card-only\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchQuery\": \"python\\nleadership\\nexcel\",\n  \"assetType\": \"ALL\",\n  \"maxResults\": 50,\n  \"includeDetails\": false\n}\n```\n\n### Example: read specific URLs\n\n```json\n{\n  \"mode\": \"byUrls\",\n  \"urls\": [\n    {\"url\": \"https://www.linkedin.com/learning/python-essential-training-18764650\"},\n    {\"url\": \"https://www.linkedin.com/learning/paths/getting-started-with-python\"},\n    {\"url\": \"https://www.linkedin.com/learning/python-quick-start-22667553/starting-with-python\"}\n  ]\n}\n```\n\n## Output per record\n\nEvery record carries `sourceUrl`, `scrapedAt` and `recordType` (`course`, `learningPath` or `video`).\n\n| Field | Notes |\n|---|---|\n| `title`, `description` | Course, path or chapter name and overview |\n| `id`, `courseId` | Stable slug id; `courseId` is the numeric slug suffix when present |\n| `courseUrl`, `sourceUrl`, `pathUrl`, `videoUrl` | Canonical public URLs |\n| `thumbnailUrl` | Cover image (public, no Referer needed) |\n| `assetType`, `recordType` | `COURSE`, `LEARNING_PATH`, `VIDEO` |\n| `language` | Content language from the course page |\n| `difficultyLevel` | `BEGINNER`, `INTERMEDIATE`, `ADVANCED` |\n| `durationSeconds`, `durationFormatted`, `duration` | Total length in seconds, e.g. `1h 54m`, and rounded minutes |\n| `instructorName`, `instructorUrl`, `instructor` | First instructor (legacy fields) |\n| `instructorNames`, `instructors` | All listed instructors with profile and image URLs |\n| `viewerCount` | LinkedIn's historical enrollment count |\n| `ratingValue`, `ratingCount` | Aggregate rating and number of ratings |\n| `skillsTaught` | Skills LinkedIn lists under \"Skills you'll gain\" |\n| `topics` | Catalog subject tags |\n| `categoryPath` | Breadcrumb path such as `Technology > Software Development > Programming Languages` |\n| `syllabus` | Section titles, durations and descriptions |\n| `chapters` | Chapter/lesson titles, URLs, durations, descriptions and free-preview flags |\n| `lessonCount`, `freeLessonCount` | Counts from the public chapter list |\n| `reviews` | Up to 3 public reviews with rating, text, author name, job title, profile URL and date |\n| `certificate`, `certificateName` | Completion certificate when LinkedIn publishes it |\n| `providerName`, `accessModel` | Course provider and access model (e.g. subscription) |\n| `learningPathCourses`, `courseCount` | Ordered member courses for learning paths |\n| `parentCourseTitle`, `parentCourseUrl` | Parent course for video chapters |\n| `releaseDate` | ISO release date |\n| `query` | The search query that produced the record |\n| `popularityScore`, `learnerCount` | Legacy aliases: rating value and rating count |\n\nFields that LinkedIn does not publish for a record are omitted. The actor never writes `null`, `N/A`, `-1` or an empty string.\n\n## Use cases\n\n- **Curriculum planning** - compare what already exists for a skill before building internal training.\n- **Skills-gap research** - export the skills and catalog categories across many queries.\n- **Learning & development catalogs** - build a searchable catalog with duration, level, provider and rating.\n- **Instructor discovery** - find who teaches in a subject and which courses they lead.\n- **Free-preview planning** - rank courses by how many lessons LinkedIn exposes for free.\n- **Catalog monitoring** - schedule the same queries and compare snapshots by `id` and `scrapedAt`.\n\n## Limitations\n\n- **50 cards per query and filter slice.** LinkedIn's guest catalog has no next-page control. The actor works around this by re-running the query across LinkedIn's own level, length and sort slices. On a broad course query this reached **about 97% of the total LinkedIn reported** (375 of 385 unique courses in testing); the run status says when a shortfall remains. Requesting more than the source exposes never invents rows.\n- **No content-language filter.** LinkedIn's guest search has no language parameter; changing the locale only changes the page language. Each record still reports the course `language`.\n- **Three reviews.** Course pages publish three review samples; the actor returns those, not the full review history.\n- **No instructor course-list page.** Instructor profile pages do not expose a public course list without a login, so there is no instructor mode.\n- **Video records are chapters.** `assetType=VIDEO` returns individual lessons/chapters with a link to their parent course, which is what LinkedIn's guest catalog exposes.\n- **Detail pages are extra requests.** `includeDetails=true` reads one page per record. Use `false` for large scheduled snapshots or set a smaller `maxResults`.\n- **Instructor profile links.** The profile URLs come from LinkedIn's public course data and open in a browser. LinkedIn sometimes answers a bare command-line request for `/in/...` with its `999` bot check, so an automated HEAD check can fail even though the link is valid.\n\n## FAQ\n\n**Do I need a LinkedIn account, a Learning subscription or cookies?**\nNo. Every request reads a public page that a signed-out visitor can open. There is no cookie input and no login field.\n\n**Why did I get fewer records than `maxResults`?**\nEither LinkedIn's catalog has fewer matches for that query and filter, or the guest page stopped exposing more. The run status reports the shortfall; split the topic into narrower queries for wider coverage.\n\n**Why do some records have fewer fields?**\nNot every public course page publishes every field. Skills, syllabus, reviews, certificate data and learner counts are optional on LinkedIn's side and are omitted when absent.\n\n**What is the difference between a course and a learning path?**\nA course is one multi-lesson unit. A learning path is a curated sequence of courses; its record includes the ordered member courses.\n\n**What is the difference between a video and a course?**\nA video record is a single chapter or lesson inside a course, with `parentCourseTitle` and `parentCourseUrl` linking back to the course.\n\n**What is `popularityScore`?**\nIt is the legacy name for LinkedIn's aggregate rating value. New integrations should use `ratingValue`; `learnerCount` is the legacy name for `ratingCount`, not the enrollment count. The enrollment count is `viewerCount`.\n\n**Does `software` accept more than one value?**\nLinkedIn applies only the first software label per request. Use one label per run; a second label in the same field is ignored by the source.\n\n**I used to set `language`. Is my saved task broken?**\nNo. The old `language` field is still accepted for saved tasks, but it never changed LinkedIn's results. The run status explains that it is no longer a filter, and every enriched record reports the course's real `language`.\n\n**Is this affiliated with LinkedIn?**\nNo. It reads LinkedIn Learning's public catalog pages and is not operated or endorsed by LinkedIn.\n\n## Local development\n\n```bash\npython -m pytest tests/ -q\napify run --purge --input-file input.json\n```\n\nThe actor uses `httpx` only; no browser, no login, no cookie.\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "linkedin-learning-course-and-learning-path-finder",
      "title": "LinkedIn Learning Course & Learning Path Finder",
      "description": "Search the public LinkedIn Learning catalog by keyword and filter by level, type, length, software and sort order. Get course, learning-path and chapter records with instructor, duration, rating, learners, skills, syllabus, reviews and certificate data. No login or cookies.",
      "version": "1.1",
      "buildTag": "latest",
      "dockerfile": "./Dockerfile",
      "readme": "# LinkedIn Learning Course & Learning Path Finder\n\nRead the public LinkedIn Learning catalog without an account, a subscription seat or a cookie. Search by keyword with LinkedIn's own filters, read specific course / learning-path / chapter URLs, or browse every learning path, and get structured records with instructor, duration, level, rating, learner count, skills, syllabus, reviews and certificate data.\n\n## What this actor does\n\n- **Searches the public catalog** by keyword, with one query per line for batch runs.\n- **Uses LinkedIn's real filters**: skill level, content type, time to complete, software label and sort order (best match, most viewed, newest).\n- **Collects past the 50-card guest page** by re-running the query across LinkedIn's own filter slices and merging unique records.\n- **Reads detail pages** for the full record: description, skills taught, syllabus sections, chapters, free-preview lessons, rating, rating count, learner count, provider, category path, reviews and certificate.\n- **Accepts URLs**: individual courses, learning paths, video chapters, topic pages and filtered search URLs.\n- **Browses all learning paths** from the public all-paths page.\n- **Skips LinkedIn's no-results fallback.** When nothing matches, LinkedIn renders a page of unrelated popular courses; the actor detects that page and returns zero records with an explanation instead of fabricated relevance.\n- **Empty fields are omitted** instead of writing nulls or sentinels.\n\n## Modes\n\n| Mode | What it needs | What it returns |\n|---|---|---|\n| `search` (default) | `searchQuery` | Courses, learning paths or video chapters matching the query and filters |\n| `byUrls` | `urls` | One record per course, learning path, chapter or search URL |\n| `learningPaths` | nothing | Up to 50 public learning paths, optionally enriched |\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | select | `search` | `search`, `byUrls` or `learningPaths` |\n| `searchQuery` | text | - | Keyword or skill. One query per line for several searches; each record is labelled with the query that found it. Required in search mode. |\n| `urls` | URL list | - | Course, learning-path, chapter/lesson, topic or filtered search URLs. Required in URL mode. |\n| `maxResults` | integer | `50` | Records per query (or per URL list). `1`-`500`. |\n| `difficultyLevel` | select | all levels | `BEGINNER`, `INTERMEDIATE`, `ADVANCED` |\n| `assetType` | select | `COURSE` | `COURSE`, `LEARNING_PATH`, `VIDEO`, or `ALL` |\n| `sortBy` | select | `RELEVANCE` | `RELEVANCE`, `POPULARITY` (view count), `RECENCY` |\n| `duration` | select | any length | Under 10 min, 10-30 min, 30-60 min, 1-2 h, 2-3 h, 3+ h |\n| `software` | text | - | One LinkedIn software label, e.g. `Python`, `Microsoft Excel`, `SQL`, `ChatGPT` |\n| `topic` | text | - | Extra words appended to every query to narrow it |\n| `includeDetails` | boolean | `true` | Open each record's public page for the full detail surface. Turn off for a faster catalog snapshot. |\n| `proxyConfiguration` | proxy | direct | Optional override. The actor connects directly by default and only escalates to a datacenter proxy if LinkedIn blocks a request. |\n\n### Example: beginner Python courses, most viewed\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchQuery\": \"Python machine learning\",\n  \"difficultyLevel\": \"BEGINNER\",\n  \"assetType\": \"COURSE\",\n  \"sortBy\": \"POPULARITY\",\n  \"maxResults\": 100\n}\n```\n\n### Example: several skills in one run, card-only\n\n```json\n{\n  \"mode\": \"search\",\n  \"searchQuery\": \"python\\nleadership\\nexcel\",\n  \"assetType\": \"ALL\",\n  \"maxResults\": 50,\n  \"includeDetails\": false\n}\n```\n\n### Example: read specific URLs\n\n```json\n{\n  \"mode\": \"byUrls\",\n  \"urls\": [\n    {\"url\": \"https://www.linkedin.com/learning/python-essential-training-18764650\"},\n    {\"url\": \"https://www.linkedin.com/learning/paths/getting-started-with-python\"},\n    {\"url\": \"https://www.linkedin.com/learning/python-quick-start-22667553/starting-with-python\"}\n  ]\n}\n```\n\n## Output per record\n\nEvery record carries `sourceUrl`, `scrapedAt` and `recordType` (`course`, `learningPath` or `video`).\n\n| Field | Notes |\n|---|---|\n| `title`, `description` | Course, path or chapter name and overview |\n| `id`, `courseId` | Stable slug id; `courseId` is the numeric slug suffix when present |\n| `courseUrl`, `sourceUrl`, `pathUrl`, `videoUrl` | Canonical public URLs |\n| `thumbnailUrl` | Cover image (public, no Referer needed) |\n| `assetType`, `recordType` | `COURSE`, `LEARNING_PATH`, `VIDEO` |\n| `language` | Content language from the course page |\n| `difficultyLevel` | `BEGINNER`, `INTERMEDIATE`, `ADVANCED` |\n| `durationSeconds`, `durationFormatted`, `duration` | Total length in seconds, e.g. `1h 54m`, and rounded minutes |\n| `instructorName`, `instructorUrl`, `instructor` | First instructor (legacy fields) |\n| `instructorNames`, `instructors` | All listed instructors with profile and image URLs |\n| `viewerCount` | LinkedIn's historical enrollment count |\n| `ratingValue`, `ratingCount` | Aggregate rating and number of ratings |\n| `skillsTaught` | Skills LinkedIn lists under \"Skills you'll gain\" |\n| `topics` | Catalog subject tags |\n| `categoryPath` | Breadcrumb path such as `Technology > Software Development > Programming Languages` |\n| `syllabus` | Section titles, durations and descriptions |\n| `chapters` | Chapter/lesson titles, URLs, durations, descriptions and free-preview flags |\n| `lessonCount`, `freeLessonCount` | Counts from the public chapter list |\n| `reviews` | Up to 3 public reviews with rating, text, author name, job title, profile URL and date |\n| `certificate`, `certificateName` | Completion certificate when LinkedIn publishes it |\n| `providerName`, `accessModel` | Course provider and access model (e.g. subscription) |\n| `learningPathCourses`, `courseCount` | Ordered member courses for learning paths |\n| `parentCourseTitle`, `parentCourseUrl` | Parent course for video chapters |\n| `releaseDate` | ISO release date |\n| `query` | The search query that produced the record |\n| `popularityScore`, `learnerCount` | Legacy aliases: rating value and rating count |\n\nFields that LinkedIn does not publish for a record are omitted. The actor never writes `null`, `N/A`, `-1` or an empty string.\n\n## Use cases\n\n- **Curriculum planning** - compare what already exists for a skill before building internal training.\n- **Skills-gap research** - export the skills and catalog categories across many queries.\n- **Learning & development catalogs** - build a searchable catalog with duration, level, provider and rating.\n- **Instructor discovery** - find who teaches in a subject and which courses they lead.\n- **Free-preview planning** - rank courses by how many lessons LinkedIn exposes for free.\n- **Catalog monitoring** - schedule the same queries and compare snapshots by `id` and `scrapedAt`.\n\n## Limitations\n\n- **50 cards per query and filter slice.** LinkedIn's guest catalog has no next-page control. The actor works around this by re-running the query across LinkedIn's own level, length and sort slices. On a broad course query this reached **about 97% of the total LinkedIn reported** (375 of 385 unique courses in testing); the run status says when a shortfall remains. Requesting more than the source exposes never invents rows.\n- **No content-language filter.** LinkedIn's guest search has no language parameter; changing the locale only changes the page language. Each record still reports the course `language`.\n- **Three reviews.** Course pages publish three review samples; the actor returns those, not the full review history.\n- **No instructor course-list page.** Instructor profile pages do not expose a public course list without a login, so there is no instructor mode.\n- **Video records are chapters.** `assetType=VIDEO` returns individual lessons/chapters with a link to their parent course, which is what LinkedIn's guest catalog exposes.\n- **Detail pages are extra requests.** `includeDetails=true` reads one page per record. Use `false` for large scheduled snapshots or set a smaller `maxResults`.\n- **Instructor profile links.** The profile URLs come from LinkedIn's public course data and open in a browser. LinkedIn sometimes answers a bare command-line request for `/in/...` with its `999` bot check, so an automated HEAD check can fail even though the link is valid.\n\n## FAQ\n\n**Do I need a LinkedIn account, a Learning subscription or cookies?**\nNo. Every request reads a public page that a signed-out visitor can open. There is no cookie input and no login field.\n\n**Why did I get fewer records than `maxResults`?**\nEither LinkedIn's catalog has fewer matches for that query and filter, or the guest page stopped exposing more. The run status reports the shortfall; split the topic into narrower queries for wider coverage.\n\n**Why do some records have fewer fields?**\nNot every public course page publishes every field. Skills, syllabus, reviews, certificate data and learner counts are optional on LinkedIn's side and are omitted when absent.\n\n**What is the difference between a course and a learning path?**\nA course is one multi-lesson unit. A learning path is a curated sequence of courses; its record includes the ordered member courses.\n\n**What is the difference between a video and a course?**\nA video record is a single chapter or lesson inside a course, with `parentCourseTitle` and `parentCourseUrl` linking back to the course.\n\n**What is `popularityScore`?**\nIt is the legacy name for LinkedIn's aggregate rating value. New integrations should use `ratingValue`; `learnerCount` is the legacy name for `ratingCount`, not the enrollment count. The enrollment count is `viewerCount`.\n\n**Does `software` accept more than one value?**\nLinkedIn applies only the first software label per request. Use one label per run; a second label in the same field is ignored by the source.\n\n**I used to set `language`. Is my saved task broken?**\nNo. The old `language` field is still accepted for saved tasks, but it never changed LinkedIn's results. The run status explains that it is no longer a filter, and every enriched record reports the course's real `language`.\n\n**Is this affiliated with LinkedIn?**\nNo. It reads LinkedIn Learning's public catalog pages and is not operated or endorsed by LinkedIn.\n\n## Local development\n\n```bash\npython -m pytest tests/ -q\napify run --purge --input-file input.json\n```\n\nThe actor uses `httpx` only; no browser, no login, no cookie.\n",
      "input": {
        "title": "LinkedIn Learning Catalog Input",
        "description": "Search the public LinkedIn Learning catalog by keyword, filter by level, type, length, software and sort order, or read specific course, learning-path and chapter URLs. No login or cookie is required.",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "mode": {
            "title": "Mode",
            "type": "string",
            "description": "What to collect. 'Search the catalog' needs searchQuery. 'Read specific URLs' needs urls. 'Browse learning paths' reads the public all-paths page.",
            "editor": "select",
            "enum": [
              "search",
              "byUrls",
              "learningPaths"
            ],
            "enumTitles": [
              "Search the catalog",
              "Read specific LinkedIn Learning URLs",
              "Browse all learning paths"
            ],
            "default": "search",
            "prefill": "search"
          },
          "searchQuery": {
            "title": "Search query",
            "type": "string",
            "description": "Keyword or skill to search for, e.g. 'Python machine learning' or 'project management'. Put one query per line to run several searches in one run; each line is labelled in the output.",
            "editor": "textfield",
            "prefill": "Python machine learning"
          },
          "urls": {
            "title": "LinkedIn Learning URLs",
            "type": "array",
            "description": "Course, learning-path, chapter/lesson, topic or filtered search URLs. Used only in 'Read specific LinkedIn Learning URLs' mode.",
            "editor": "requestListSources",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "title": "URL",
                  "type": "string",
                  "description": "LinkedIn Learning course, learning-path, chapter/lesson, topic or filtered search URL."
                }
              }
            },
            "default": [],
            "prefill": []
          },
          "maxResults": {
            "title": "Max results per query",
            "type": "integer",
            "description": "Maximum records per query (or per URL list in URL mode). LinkedIn's guest catalog exposes at most 50 cards per filter slice; the actor re-runs the query across its own filters to collect more.",
            "editor": "number",
            "minimum": 1,
            "maximum": 500,
            "default": 50,
            "prefill": 3
          },
          "difficultyLevel": {
            "title": "Difficulty level",
            "type": "string",
            "description": "Filter by skill level. 'All levels' returns every level.",
            "editor": "select",
            "enum": [
              "",
              "BEGINNER",
              "INTERMEDIATE",
              "ADVANCED"
            ],
            "enumTitles": [
              "All levels",
              "Beginner",
              "Intermediate",
              "Advanced"
            ],
            "default": "",
            "prefill": "",
            "sectionCaption": "Search filters",
            "sectionDescription": "Server-side filters from LinkedIn Learning's own catalog. They apply only in search mode (and to search URLs in URL mode)."
          },
          "assetType": {
            "title": "Asset type",
            "type": "string",
            "description": "Kind of learning content. 'All types' mixes courses, learning paths and videos.",
            "editor": "select",
            "enum": [
              "COURSE",
              "LEARNING_PATH",
              "VIDEO",
              "ALL"
            ],
            "enumTitles": [
              "Course",
              "Learning path",
              "Video (chapter)",
              "All types"
            ],
            "default": "COURSE",
            "prefill": "COURSE"
          },
          "sortBy": {
            "title": "Sort by",
            "type": "string",
            "description": "Order of the results: LinkedIn's best match, view count, or newest release.",
            "editor": "select",
            "enum": [
              "RELEVANCE",
              "POPULARITY",
              "RECENCY"
            ],
            "enumTitles": [
              "Best match",
              "Most viewed",
              "Newest"
            ],
            "default": "RELEVANCE",
            "prefill": "RELEVANCE"
          },
          "duration": {
            "title": "Time to complete",
            "type": "string",
            "description": "Filter by total course length. 'Any length' returns every length.",
            "editor": "select",
            "enum": [
              "",
              "BETWEEN_0_TO_10_MIN",
              "BETWEEN_10_TO_30_MIN",
              "BETWEEN_30_TO_60_MIN",
              "BETWEEN_1_TO_2_HOURS",
              "BETWEEN_2_TO_3_HOURS",
              "MORE_THAN_3_HOURS"
            ],
            "enumTitles": [
              "Any length",
              "Under 10 minutes",
              "10-30 minutes",
              "30-60 minutes",
              "1-2 hours",
              "2-3 hours",
              "3+ hours"
            ],
            "default": "",
            "prefill": ""
          },
          "software": {
            "title": "Software",
            "type": "string",
            "description": "Keep only content that teaches this LinkedIn Learning software label, e.g. 'Python', 'Microsoft Excel', 'SQL' or 'ChatGPT'. LinkedIn applies only one software label per request.",
            "editor": "textfield"
          },
          "topic": {
            "title": "Extra keywords",
            "type": "string",
            "description": "Optional words appended to every search query to narrow it, e.g. 'AWS' or 'for beginners'.",
            "editor": "textfield"
          },
          "includeDetails": {
            "title": "Include full course details",
            "type": "boolean",
            "description": "Open each record's public page for description, skills, syllabus, chapters, free-preview flags, reviews, rating, learner count, provider and certificate. Turn off for a faster, cheaper catalog snapshot.",
            "editor": "checkbox",
            "default": true,
            "prefill": false,
            "sectionCaption": "Output and connection",
            "sectionDescription": "Detail enrichment and optional connection settings."
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Optional. The actor connects directly by default and only escalates to a datacenter proxy if LinkedIn blocks a request. Change this only if you need a specific proxy setup.",
            "editor": "proxy",
            "prefill": {
              "useApifyProxy": false
            },
            "default": {
              "useApifyProxy": false
            }
          }
        },
        "required": [
          "mode"
        ]
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "LinkedIn Learning Catalog Output",
        "description": "LinkedIn Learning courses, learning paths and video chapters matching the input, with instructor, duration, level, rating, learners, skills, syllabus, reviews and certificate data where LinkedIn publishes them.",
        "properties": {
          "records": {
            "type": "string",
            "title": "LinkedIn Learning records",
            "description": "Dataset containing every course, learning-path and video record collected by this run.",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "views": {
            "overview": {
              "title": "Learning records",
              "transformation": {
                "fields": [
                  "title",
                  "assetType",
                  "instructorName",
                  "durationFormatted",
                  "difficultyLevel",
                  "ratingValue",
                  "viewerCount",
                  "courseUrl"
                ]
              },
              "display": {
                "component": "table",
                "properties": {}
              }
            }
          }
        }
      },
      "environmentVariables": {}
    },
    "buildNumber": "1.1.1",
    "imageDigest": "22ce71c25b5dd203e5baf5fde9bdf6b32007b4c1fb41693c552d53843e0d161a",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "1.1"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.012117777777777778
    }
  }
}