LinkedIn Learning MCP server

Registry name: io.github.johnisanerd/linkedin-learning. Maintained by AlphaOSINT (Apify developer johnvc, GitHub johnisanerd).

What it does

Search LinkedIn Learning courses by keyword, level, length or software and get full course records with rating, review text, syllabus, instructors, skills and certificates.

Course catalog data for training and upskilling. Use it for learning-path recommendations, course comparison and skills research.

This server is not self-hosted. It runs on Apify’s hosted MCP endpoint (mcp.apify.com), which starts the Apify Actor johnvc/linkedin-learning-api for each tool call. You need an Apify account, and every call is billed to that account at the Actor’s prices below. Apify’s own pricing and terms apply to the account.

Charge Price (USD) What it covers
Course found $0.00001 Charged once for each course returned by a search or topic page, with its title, instructors, length, level, thumbnail and link. Not charged for duplicates, for the popular-courses list LinkedIn shows when a query match…
Full course record $0.00001 Charged once for each full course record returned: rating, learner reviews, the complete syllabus with per-lesson descriptions, free-lesson flags, instructors, skills and certificate details. Replaces the search charge…

Prices shown are Apify’s free-plan rates; paid Apify plans get lower per-event prices. Apify also bills a token amount per run start and per stored row ($0.00001, $0.00001). Prices change from time to time; the Actor’s page on Apify shows the current ones.

Data source and terms

LinkedIn Learning’s public course pages, collected by scraping. No login or cookies are used. The server returns the data as published at the time of the call. You are responsible for using it in line with the source’s terms and the laws that apply to you. AlphaOSINT is not affiliated with the source.

Endpoint

Setup

Claude Code

claude mcp add --transport http linkedin-learning "https://mcp.apify.com/?tools=johnvc/linkedin-learning-api"

VS Code (.vscode/mcp.json)

{
  "servers": {
    "linkedin-learning": {
      "type": "http",
      "url": "https://mcp.apify.com/?tools=johnvc/linkedin-learning-api"
    }
  }
}

Cursor (~/.cursor/mcp.json)

{
  "mcpServers": {
    "linkedin-learning": {
      "url": "https://mcp.apify.com/?tools=johnvc/linkedin-learning-api"
    }
  }
}

Claude Desktop (Settings → Connectors → Add custom connector, paste the URL). Older versions without remote connectors can bridge through mcp-remote in claude_desktop_config.json:

{
  "mcpServers": {
    "linkedin-learning": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://mcp.apify.com/?tools=johnvc/linkedin-learning-api"
      ]
    }
  }
}

Each client opens an Apify sign-in (OAuth) on first use. To use a token instead, send Authorization: Bearer <APIFY_TOKEN> as a header; create one under Apify Console → Settings → API & Integrations.

Tools

Tool What it does
johnvc--linkedin-learning-api Runs the Actor with the parameters below and returns the result rows.
get-actor-run Status of a run started by the tool, for long runs.
get-dataset-items Pages through a run’s full output by datasetId when it is larger than the inline result.
get-key-value-store-record Reads a record a run stored, such as a run report.
abort-actor-run Stops a run.

Apify’s endpoint adds the four helper tools automatically whenever an Actor tool is loaded.

Parameters of johnvc--linkedin-learning-api

Parameter Type Required Default Description
mode string: search, details yes "search" Choose what to collect. Use ‘search’ to find courses by keyword with filters, or ‘details’ to pull the full record for course URLs you already have (ratings, reviews, syllabus, instructors, certificate).
queries array   ["python"] Keywords to search, one per line. Each query is searched separately and its results are labelled with the query that found them. Used in ‘search’ mode only. Leave empty if you are browsing topic pages instead.
topics array   [] Optional LinkedIn Learning topic slugs or topic URLs to browse, such as ‘python’ or https://www.linkedin.com/learning/topics/python. Topic pages are an alternative to keyword search and return the same course fields.
sortBy string: RELEVANCE, POPULARITY, RECENCY   "RELEVANCE" Order the search results. ‘Most relevant’ is LinkedIn’s default ranking, ‘Most popular’ favours high view counts, and ‘Newest’ favours recent release dates.
difficultyLevel string: ANY, BEGINNER, INTERMEDIATE, ADVANCED   "ANY" Keep only courses at one skill level. Leave as ‘Any level’ to include all of them.
entityType string: ANY, COURSE, VIDEO, LEARNING_PATH   "ANY" Keep only one kind of content. Courses are full multi-lesson courses, videos are single lessons, and learning paths are curated multi-course tracks.
duration string: ANY, BETWEEN_0_TO_10_MIN, BETWEEN_10_TO_30_MIN, BETWEEN_30_TO_60_MIN, B…   "ANY" Keep only courses that fall in one length bracket.
softwareNames array   [] Keep only courses that teach this tool, using LinkedIn’s own label such as Python, Microsoft Excel, SQL, ChatGPT or Claude. The schema accepts up to 10, but LinkedIn applies only the first label it receives, so pass one…
maxItems integer   50 How many courses to return for each query. LinkedIn serves at most 50 results per query and filter combination, so ask for more than 50 only with ‘Widen coverage’ turned on. Up to 1000 per query. Need larger batches? Co…
expandWithFilters boolean   false Run the same query again across LinkedIn’s own filter combinations (sort order, content type, difficulty, length) and merge the unique courses. This is the only way past the 50-per-query ceiling. It fetches more pages a…
enrichDetails boolean   false Open each course found by the search and return its full record, including rating, review text, syllabus and instructors. Enriched rows are billed at the course details rate instead of the search result rate, never both…
courseUrls array   [] LinkedIn Learning course, lesson or learning path URLs to collect in full, one per line. A course URL returns the full course record, a lesson URL returns that lesson linked to its parent course, and a learning path URL…
maxConcurrency integer   5 How many course pages to read at once, in both ‘details’ mode and when ‘Include full course details’ is on. Raise it to finish a large run faster, lower it if you ever see rate limiting.
requestTimeoutSecs integer   40 How long to wait for a single page before giving up and retrying it.

Example arguments:

{
  "helloWorld": 123
}

Output

The tool returns JSON rows with these fields.

Field Type Description
resultType string: search_result, course_detail, lesson, learning_path… Which kind of row this is: a search result, a full course record, a lesson, a learning path, a no-match notice, or an error for one input.
title string Course, lesson, or learning path title as published on LinkedIn Learning.
courseUrl string Canonical LinkedIn Learning course link with tracking parameters removed.
courseId string Identifier for the COURSE, taken from the trailing number in its URL, or the URL slug when a course has no number. A lesson row carries its parent course’s id, so lessons can be joined to their course; use courseUrl or…
sourceUrl string The URL supplied as input or the page this row was read from.
lessonUrl string Direct link to a single lesson, when the row is a lesson.
pathUrl string Direct link to a learning path, when the row is a learning path.
description string Full course description as published on the course page.
difficultyLevel string Skill level LinkedIn assigns to the course.
entityType string: COURSE, VIDEO, LEARNING PATH Whether the search result is a course, a single video lesson, or a learning path. LinkedIn labels these COURSE, VIDEO and LEARNING PATH.
instructors array Everyone credited as an instructor. Search rows carry the name only; full course records add job title, LinkedIn profile link and photo.
skills array Skills and technologies the course covers, each linking to its LinkedIn Learning topic page.
categoryPath array Category hierarchy the course sits in, from broadest to narrowest.
durationText string Course length as published, in ISO 8601 form on detail rows and as displayed text on search rows.
durationSeconds integer Course length in whole seconds, parsed for sorting and filtering.
enrollmentCount integer How many people have taken the course to date.
ratingValue number Average learner rating out of 5.
ratingCount integer How many learners rated the course.
reviews array Written learner reviews with the rating, the review text, and the reviewer’s name, job title and profile link.
tableOfContents array Full syllabus: every section with its lessons, each carrying a title, a written description, its length, and whether it can be watched free.
lessonCount integer How many lessons the course contains.
freeLessonCount integer How many lessons can be watched without a subscription.
hasCertificate boolean Whether the course awards a certificate of completion.
certificateName string Name of the credential awarded.
accessModel string How the course is made available. LinkedIn Learning courses are subscription based and carry no individual price.
language string Language the course is taught in.
provider string Organization publishing the course.
dateCreated string When the course was created.
datePublished string When the course was published.
thumbnailUrl string Course artwork image link. The query string is part of the signed image URL and is preserved.
isFree boolean Whether this lesson can be watched without a subscription.
requiresSubscription boolean Whether this lesson needs a LinkedIn Learning subscription.
courses array Courses that make up a learning path, in order.
courseCount integer How many courses the learning path contains.
searchQuery string The query or topic that returned this row.
searchType string: query, topic Whether the row came from a keyword search or a topic page.
searchPosition integer Rank this course held in the search results that found it, on enriched rows.
position integer Rank of this result within its search page, starting at 1.
appliedFilters object Which LinkedIn filters were in force for the request that surfaced this row.
approximateTotalResults integer How many courses LinkedIn reports for this query. Approximate: the same query can report different totals across page variants, so treat it as a size signal rather than an exact count.
viewersText string Viewer count as displayed on the search card.
releaseText string Release date as displayed on the search card.
parseSource string: jsonld, dom Whether the record was read from the page’s structured data or from its markup.
message string Explanatory note, used on no-match rows.
errorType string Category of failure for an error row.
errorMessage string What went wrong, phrased for the person running the actor.
httpStatus integer Status code LinkedIn returned, when there was one.
fetchedAt string When this row was collected, in UTC.
fromCache boolean True when this course record was served from the shared result cache instead of a new page read; fetchedAt then holds the time it was originally read. Billed like a fresh record. Only full course records are cached; sea…