# LinkedIn Jobs Scraper | No Login, Exact Country Filter (`aurelix/linkedin-jobs`) Actor

Scrape LinkedIn jobs with LinkedIn's exact country id picked for you, where the most-used LinkedIn scrapers need a manual geoId or city text; other-country results dropped and filtered-out jobs free. No login: title, company, salary, job type, date. $1.50 per 1,000.

- **URL**: https://apify.com/aurelix/linkedin-jobs.md
- **Developed by:** [Aurelix](https://apify.com/aurelix) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.05 / 1,000 job 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

### What is LinkedIn Jobs Scraper?

**Export LinkedIn jobs for any keyword and country to Excel, CSV or JSON (title, company, salary, job type, posted date) for $1.50 per 1,000 jobs, no login.**

For job boards, recruiters and labour-market researchers. LinkedIn's exact country ID is picked for you, jobs from other countries are dropped, and filtered-out or duplicate jobs are never charged. Your first run with the example input costs about $0.015 (10 jobs in our test run).

[![LinkedIn Jobs Scraper: example output from a real run](https://api.apify.com/v2/key-value-stores/twkCCtTWzsi8fVbx5/records/linkedin-jobs-card-v3.png)](https://console.apify.com/actors/AbVuu9LNiPfGWwzqY?addFromActorId=AbVuu9LNiPfGWwzqY)

[![LinkedIn Jobs Scraper: 75-second demo video](https://api.apify.com/v2/key-value-stores/twkCCtTWzsi8fVbx5/records/linkedin-jobs-demo-thumb-v1.png)](https://api.apify.com/v2/key-value-stores/twkCCtTWzsi8fVbx5/records/linkedin-jobs-demo-v1.mp4)

**[▶ Watch the 75-second demo](https://api.apify.com/v2/key-value-stores/twkCCtTWzsi8fVbx5/records/linkedin-jobs-demo-v1.mp4)**

| | |
|---|---|
| **Search by** | Keywords + country/location, or LinkedIn job search URLs |
| **Filters** | Date posted, job type, experience level, workplace type (date re-checked on every result; job type and level whenever details are on) |
| **Output** | 19 fields per job; JSON, CSV, Excel, API |
| **Automate** | Schedules, webhooks, Zapier, Make, n8n, Google Sheets, MCP for AI agents |
| **Price** | $1.50 per 1,000 jobs ($1.05 per 1,000 jobs on paid Apify plans) |
| **Login needed** | No |

### Why LinkedIn Jobs Scraper users pick this one

- **Results stay in your country.** LinkedIn's exact country ID; jobs from other countries are dropped.
- **Filters that actually filter.** Date posted re-checked on every result; job type whenever details are on.
- **Exact limits.** Ask for 100 jobs, get and pay for at most 100.
- **A fresh-jobs feed.** New-jobs-only mode for job boards and newsletters.
- **Misses are free.** Filtered-out, unrelated and duplicate jobs are never charged.

### Get started in 3 steps

1. Type job keywords (e.g. 'data engineer') or paste LinkedIn job search URLs.
2. Optionally pick a country, location, date posted, job types, experience levels, workplace types and the exact number of jobs per search.
3. Click Start, then download JSON, CSV or Excel, or schedule it and send results to Google Sheets, Zapier, Make or n8n.

**[▶ Try it with the example input](https://console.apify.com/actors/AbVuu9LNiPfGWwzqY?addFromActorId=AbVuu9LNiPfGWwzqY)**

The form opens with an example input already filled in: that run costs about $0.015 on the free plan.

### How much does it cost to scrape LinkedIn jobs?

Pay per event: you pay only for what the run returns, plus a small start fee. Bronze, Silver, Gold and higher Apify plans pay less per result.

| Jobs | Free plan | Paid plans (Bronze, Silver, Gold) |
|---|---|---|
| 100 | $0.15 | $0.11 |
| 1,000 | $1.50 | $1.05 |
| 10,000 | $15.00 | $10.50 |

Totals include the $0.00005 start fee per run, rounded to the cent. Apify's free plan includes $5 of credit a month, enough for about 3,300 jobs.

Apify datacenter proxy is included in the price; no other proxy is used. Dropped and duplicate jobs are never charged.

#### Billing events

| Event | Free plan | Paid plans (Bronze, Silver, Gold) |
|---|---|---|
| `job-result` | $1.50 per 1,000 jobs | $1.05 per 1,000 jobs |
| `apify-actor-start` | $0.00005 per run | $0.00005 per run |

### LinkedIn Jobs Scraper vs alternatives

| | **This Actor** | curious_coder/linkedin-jobs-scraper | valig/linkedin-jobs-scraper |
|---|---|---|---|
| **Price per 1,000 jobs, free plan** | $1.50 (changing to $0.50 soon) | $2.00 | $0.40 |
| **Price per 1,000 jobs, paid plans** | $1.05 (changing to $0.40 soon) | $1.00 | $0.36 |
| **Start fee per run** | $0.00005 (changing to $0.0005 soon) | $0.00005 | $0.001 ($0.0009 paid) |
| **Platform usage billed on top** | No | No | No |
| **Country picked by LinkedIn's exact country id** | ✓ | Manual geoId | ✗ (city, state or zip text) |
| **Results naming another country dropped** | ✓ | not stated | not stated |
| **Job type and level filters re-checked on each job page** | ✓ with details on (default; level where shown) | ✗ | ✗ |
| **Jobs dropped by your filters not charged** | ✓ | not stated | not stated |
| **Only-new-jobs mode for scheduled runs** | ✓ | not stated | Manual (skip job IDs) |
| **Slack or webhook digest after each run** | ✓ | not stated | not stated |

Prices checked regularly on each Actor's Store page.

### Benchmarks: how we compare

| Run | Jobs returned | Run time | What we checked |
|---|---|---|---|
| Prefilled form: data engineer, 10 jobs | 10 | not recorded | Charged $0.015 in total |
| nurse, actuary, data engineer, pharmacist; US; 50 each; details on | 200 (50 each) | 229-254 s per search | 200 of 200 relevant to the keyword, incl. 'RN' and 'Actuarial Analyst' titles; no relevant card dropped |
| Same 200 jobs: fields filled | 200 | - | seniority, employment type, industries, applicants and description 200/200; company page 196/200; salary 19/200 (only where LinkedIn shows one) |
| 10 jobs against the public job page | 10 | - | 10 of 10 field by field: title, company, location, seniority, employment type, industries, posted age, salary |
| actuary, Canada, past month, details off, max 100 | 100 | 34 s | Exact limit |
| actuary, Canada, past month, details off, max 1,000 | 800 | 146 s | All jobs the search yielded after the keyword check |
| US, past week, full-time, datacenter proxy | 30 | not recorded | 4 HTTP 429 refusals recovered; 1 job dropped by the job-type re-check |
| 3 keywords, US, 150 each, no proxy (stress test) | 450 | 673 s | 62 HTTP 429 refusals recovered by back-off; run succeeded |
| Local test: 429 on 2 of 10 job pages | 8 | - | 8 jobs delivered, 2 skipped and counted in the status message; run succeeded |
| Only new jobs: max 5, then max 10, then max 10 again | 5, then 10, then 10 | 4 s and 6 s (first two) | 0 repeats; already-seen jobs do not count toward the limit |
| Nonsense keyword, US, max 50 | 0 | 5 s | Run succeeded; no job charges |

Single runs on the Apify cloud with the datacenter proxy unless the row says otherwise, taken from our test logs; the 429 test ran locally against saved LinkedIn pages with refusals injected. Relevance was judged by reading every title; field accuracy compared 10 random jobs with linkedin.com/jobs/view. Run times depend on how often LinkedIn rate-limits.

### What data you get

**LinkedIn Jobs Scraper** turns public LinkedIn job postings into clean rows: title, company, location, salary where LinkedIn shows it, seniority, job type, posted date, job link and the full description. Search by keyword and country (LinkedIn's exact country id, so results stay in the country you picked), or paste LinkedIn job search URLs. Jobs that fail your filters are dropped and never charged.

- Title, company and company LinkedIn page
- Location and detected ISO country codes
- Posted date (ISO 8601) and relative age
- Clean job link (no tracking parameters)
- Seniority level, employment type, industries
- Applicant count as shown, salary where LinkedIn shows it
- Full description as text and HTML

| title | company | location | posted_date | seniority | employment_type | job_url |
|---|---|---|---|---|---|---|
| Data Engineer | Samsara | Toronto, Ontario, Canada | 2026-10-30 | Mid-Senior level | Full-time | https://www.linkedin.com/jobs/view/4483401370/ |
| Ingénieur principal de données | LGS, an IBM Company | Montreal, Quebec, Canada | 2026-10-30 | Mid-Senior level | Full-time | https://www.linkedin.com/jobs/view/4477480926/ |
| Data Engineer (Snowflake, Azure Data Factory, Python & SQL) | Cognizant | Halifax, Nova Scotia, Canada | 2026-10-29 | Mid-Senior level | Full-time | https://www.linkedin.com/jobs/view/4458304201/ |

One full job record, exactly as a real run returned it (long text and lists shortened here). From a real run:

```json
{
  "job_id": "4466544261",
  "title": "Data Engineer I",
  "company": "Docebo",
  "company_url": "https://www.linkedin.com/company/docebo",
  "location": "Toronto, Ontario, Canada",
  "countries": [
    "CA"
  ],
  "posted_date": "2026-09-15",
  "posted_ago": "1 month ago",
  "job_url": "https://www.linkedin.com/jobs/view/4466544261/",
  "seniority": "Entry level",
  "employment_type": "Full-time",
  "industries": "Software Development",
  "applicants": "Over 200 applicants",
  "salary_text": "CA$68,600.00/yr - CA$91,500.00/yr",
  "description_text": "Artificial Intelligence. Actual Impact.\n\nAt Docebo, we’re using AI to change how people learn at work—and we mean actual... [7131 more characters]",
  "description_html": "<strong>Artificial Intelligence. Actual Impact.<br/><br/></strong>At Docebo, we’re using AI to change how people learn a... [7612 more characters]",
  "search_country": "CA",
  "source_url": "https://www.linkedin.com/jobs/view/4466544261/",
  "scraped_at": "2026-11-04T11:17:58Z"
}
```

### Use cases

- Recruiters and staffing agencies tracking new roles in one country
- Job boards and newsletters backfilling fresh postings daily with the new-jobs-only mode
- Market researchers measuring hiring demand by title, city or seniority
- Sales teams spotting companies that are hiring for a role they sell to

### Use-case recipes

#### Daily new-roles feed for one country

For job boards, newsletters and recruiters. Set the roles you cover as keywords, pick the country, choose Past 24 hours and switch on 'Only new jobs since last run', then schedule it daily. Use `job_id` as the key in your database and `job_url` as the link; jobs already returned are skipped and not charged.

```json
{
  "keywords": [
    "data engineer",
    "analytics engineer"
  ],
  "country": "CA",
  "datePosted": "past24h",
  "incremental": true,
  "maxResultsPerSearch": 50
}
```

#### Hiring-demand snapshot by seniority

For labour-market researchers. Run one role for the past month with details on. Count rows by `seniority`, `employment_type` and `location` to see where demand sits; `applicants` gives LinkedIn's competition hint for each posting.

```json
{
  "keywords": [
    "registered nurse"
  ],
  "country": "US",
  "datePosted": "pastMonth",
  "jobTypes": [
    "fullTime"
  ],
  "maxResultsPerSearch": 100
}
```

#### Fast list of companies hiring for what you sell

For sales teams. Search the job titles that signal a need for your product with details off, which is faster and returns title, company, location, date and link. Group by `company` and `company_url`, then add the companies that show up often to Hiring Signal Monitor for weekly changes.

```json
{
  "keywords": [
    "salesforce administrator"
  ],
  "country": "GB",
  "datePosted": "pastWeek",
  "includeDetails": false,
  "maxResultsPerSearch": 100
}
```

#### Re-run a search you built on LinkedIn

For anyone who already has a working search on linkedin.com/jobs. Copy the URL from the address bar into Search URLs; its keywords, location or geoId and filters are kept. Schedule it with new-only mode to watch that exact search.

```json
{
  "searchUrls": [
    "https://www.linkedin.com/jobs/search/?keywords=python&geoId=101174742&f_TPR=r604800"
  ],
  "maxResultsPerSearch": 25,
  "incremental": true
}
```

### Input

| Field | Type | What it does | Default |
|---|---|---|---|
| `keywords` (Job keywords) | array | One search per entry, e.g. \['data engineer', 'nurse']. |  |
| `maxResultsPerSearch` (Max jobs per search) | integer | Exact upper limit of jobs returned for each keyword or URL. | 50 |
| `country` (Country) | string | Restrict to one country using LinkedIn's exact country id (not fuzzy text), and drop any result whose location names another... |  |
| `location` (Location (optional)) | string | City or region as typed on LinkedIn, e.g. 'Toronto, Ontario, Canada'. |  |
| `datePosted` (Date posted) | string | Only jobs posted within this window. | "any" |
| `jobTypes` (Job types) | array | Any of: fullTime, partTime, contract, temporary, internship, volunteer, other. |  |

All 15 fields, with examples: see the **Input** tab.

### Switching from curious_coder/linkedin-jobs-scraper

Already running `curious_coder/linkedin-jobs-scraper`? Map its input fields to this Actor's like this:

| `curious_coder/linkedin-jobs-scraper` input | This Actor's input | Notes |
|---|---|---|
| `urls` | `searchUrls` | Paste the same linkedin.com/jobs/search URLs. Their own filters go to LinkedIn as they are; only keyword relevance is re-checked on their results. |
| `limitPerSource` | `maxResultsPerSearch` | Exact cap per keyword or URL, 1 to 1,000 (default 50). You get and pay for at most that many. |
| `keywords` | `keywords` | Theirs is one string; ours is a list, one search per entry. |
| `location` | `country` + `location` | Pick the country from the list to use LinkedIn's exact country id; location text such as 'Toronto, Ontario, Canada' narrows within it. |
| `geoId` | `country` | No geoId lookup for the 30 listed countries. For any other place, put its geoId in a search URL. |
| `datePosted` | `datePosted` | any, past24h, pastWeek or pastMonth; results are re-checked against the posted date. |
| `companyIds` | `searchUrls` with `f_C=` | No separate field: add f_C=<company id> to a search URL and it is passed through. |
| `scrapeCompany` | no equivalent | You get the company name and its LinkedIn company page URL, not company details. |
| `under10Applicants` | no equivalent | The `applicants` field holds LinkedIn's count text (e.g. 'Over 200 applicants') when details are on; filter after the run. |
| `splitByLocation` | no equivalent | LinkedIn shows about 1,000 jobs per search; add one keyword or search URL per city instead. |

- Output naming: one row per job with `job_id` (LinkedIn's numeric id), `job_url` (a clean /jobs/view/ link without tracking), `posted_date`, `seniority`, `employment_type`, `salary_text`, `countries` and `search_country`.
- A job found by several keywords or URLs in one run is returned once and charged once.
- Pricing is per job returned; jobs dropped by the keyword, country, date, job type or level checks are free. The comparison table above shows $1.50 per 1,000 jobs on the free plan against their $2.00.
- There is no proxy setting: every run uses Apify datacenter proxy, included in the price.

### Use with AI agents (Apify MCP server, Claude, ChatGPT, n8n AI agent)

LinkedIn Jobs Scraper is a ready-made tool for AI agents. Through the Apify MCP server an agent reads this Actor's input schema, fills in the input from your request, starts the run and reads the jobs back. You pay the same per-result price as a run started by hand, from your own Apify account.

#### Example prompts

- "Find 50 data engineer jobs in Canada posted on LinkedIn in the past week and give me a table with company, city, seniority and job link"
- "Pull full-time registered nurse jobs in the United States from LinkedIn posted in the last 24 hours and count them by city"
- "Get 100 product manager jobs in the United Kingdom from LinkedIn and list the companies hiring, with the salary where LinkedIn shows one"

#### Claude (claude.ai and Claude Desktop)

Open **Settings > Connectors**, choose **Add custom connector**, paste `https://mcp.apify.com/?tools=aurelix/linkedin-jobs` and sign in to Apify when asked. Then ask Claude one of the prompts above.

#### Claude Code, Cursor, VS Code and other MCP clients

```bash
claude mcp add --transport http apify "https://mcp.apify.com/?tools=aurelix/linkedin-jobs"
```

Clients configured with JSON take the same URL:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=aurelix/linkedin-jobs"
    }
  }
}
```

A client without Apify sign-in sends the header `Authorization: Bearer <YOUR_APIFY_TOKEN>`; to run the server locally instead, use `npx -y @apify/actors-mcp-server --actors aurelix/linkedin-jobs` with `APIFY_TOKEN` set.

#### ChatGPT

Where your ChatGPT plan offers custom connectors (developer mode), add `https://mcp.apify.com/?tools=aurelix/linkedin-jobs` as a connector, sign in to Apify, and ask for the data in plain words.

#### n8n AI agent

Give an **AI Agent** node an **MCP Client Tool** with the endpoint `https://mcp.apify.com/?tools=aurelix/linkedin-jobs` and a Bearer credential holding your Apify token. The agent can then call LinkedIn Jobs Scraper whenever a workflow step needs jobs; for a fixed, non-agent workflow use Apify's n8n node with **Run Actor** instead.

### Use it from AI agents (MCP), the API or no-code

#### Copy this to your AI assistant

```text
Use the Apify Actor aurelix/linkedin-jobs (LinkedIn Jobs Scraper) through Apify's MCP server or API. Main input: keywords (Job keywords); maxResultsPerSearch (Max jobs per search). Example input: {"keywords": ["data engineer", "product manager"], "country": "CA", "datePosted": "pastWeek", "jobTypes": ["fullTime"], "maxResultsPerSearch": 100}. Each result is one job with fields such as job_id, title, company, company_url, location, countries, posted_date, posted_ago. It costs $1.50 per 1,000 jobs on Apify's free plan plus a $0.00005 start fee per run, and needs no login.
```

MCP server URL for this Actor: `https://mcp.apify.com/?tools=aurelix/linkedin-jobs` (setup for each client in the section above).

#### API

Start a run and read the dataset with Apify's REST API or the Python and JavaScript clients:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("aurelix/linkedin-jobs").call(run_input={"keywords": ["data engineer", "product manager"], "country": "CA", "datePosted": "pastWeek", "jobTypes": ["fullTime"], "maxResultsPerSearch": 100})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

#### No-code: schedule it in 3 clicks

Send the results to Google Sheets, Zapier, Make, n8n, Slack or any webhook URL.

1. Fill in the input, then click **Save as a new task**.
2. In the task, click **Schedule** and pick daily or weekly (Apify Schedules).
3. Turn on **Only new jobs since last run** so each run returns only what is new, and paste a Slack or webhook URL into **Slack webhook URL** / **Webhook URL** to get a digest of the new items (count plus the top 10) after every run.

Prefer n8n or Make? Ask in the **Issues** tab and we will share a ready-made workflow for it.

### FAQ

#### Can I scrape LinkedIn jobs without login?

No. The Actor reads only LinkedIn's public job pages that anyone can open without logging in. It never logs in and never uses cookies from an account.

#### Is there a LinkedIn jobs API?

You can use this Actor as one. Start it with Apify's REST API or the Python and JavaScript clients and read the results as JSON (see the code above), or call it from an AI agent through MCP.

#### How much does it cost to scrape LinkedIn jobs?

About $1.50 for 1,000 jobs on Apify's free plan and $1.05 on paid plans, start fee included. The free $5 monthly credit covers about 3,300 jobs.

#### Can I export LinkedIn jobs data to Excel or Google Sheets?

Yes. Download the results as Excel, CSV, JSON, XML or HTML from the run's **Storage** tab, or send them to Google Sheets with Apify's Google Sheets integration or the API.

#### Is it legal to scrape LinkedIn jobs?

It reads only public data any logged-out visitor can see: LinkedIn job postings. It goes at a polite pace, never logs in and never solves CAPTCHAs. It returns job posting fields (title, company, location, dates, description, link); personal emails in descriptions are removed and no member profiles or recruiter cards are read. To have a record removed, open an issue on this Actor's Issues tab; if LinkedIn formally asks us to stop, this Actor will stop. You are responsible for using the data lawfully, incl. anti-spam and privacy laws; this is not legal advice.

#### Will my LinkedIn account get blocked?

No. It never uses a LinkedIn account, so there is none to block. It reads LinkedIn's public job search, the pages a logged-out visitor sees.

#### Why did I get fewer jobs than the limit?

LinkedIn shows at most about 1,000 jobs per search, and results whose location, date, type or level do not match your filters are dropped (counted in the log). Narrow searches can have fewer matches.

#### How is the country filter made correct?

Instead of free-text location, the search uses LinkedIn's numeric country id (verified for 30 countries), then any result whose location clearly names another country is removed.

#### What happens when LinkedIn rate-limits?

On HTTP 429 the Actor waits (honouring Retry-After, doubling each time) and switches to a fresh proxy session. A search stops after six straight refusals and other searches carry on. The run still succeeds with the jobs it found, and its status message names the searches that stopped early.

#### What am I charged for an empty or partial run?

Only jobs written to the dataset are charged, plus the small per-run start fee. Jobs dropped by the keyword, country, date, job type or level checks, duplicates and already-seen jobs are free. A search whose result pages show no matching titles three pages in a row stops early: in our test a nonsense keyword finished in about 5 s with 0 jobs. If LinkedIn rate-limits a search, the jobs found so far are kept and charged, and the status message names the searches that stopped. A run fails only when the input is invalid, or when every search failed and nothing was found.

#### How are duplicates handled?

By LinkedIn's job id. A job found by several keywords or search URLs in the same run is returned once, by the first search that finds it, and charged once. Across runs, switch on 'Only new jobs since last run'.

#### How long does a run take?

With details on, the Actor opens each job's public page, two at a time with short pauses, so it is polite and slower: in our test runs 50 jobs per search took about 4 minutes. With details off it reads only search pages: 100 jobs in 34 s and 800 jobs in about 2.5 minutes. LinkedIn rate-limiting adds waits.

#### What changes when I turn off 'Include description, seniority and employment type'?

Each job then comes from the search card only: title, company, company page, location, countries, posted date, job link and salary text where the card shows it. Seniority, employment type, industries, applicants, posted age and description stay empty. The keyword check then looks at the title only, and the job type and experience level re-checks are skipped. The price per job is the same.

#### How does 'Only new jobs since last run' work?

The Actor remembers the job ids it returned for the same searches (keywords, country, location, filters and sort, or the URL's parameters) or for the state name you set. Already-seen jobs are skipped, free, and do not count toward 'Max jobs per search', so each run can fill its limit with new jobs. Ids are forgotten 60 days after they were last seen. Add a Slack or webhook URL to get the count and the top 10 new jobs after each run.

#### Which countries and languages are supported?

The Country list has 30 countries with LinkedIn's exact country id: US, CA, GB, IE, DE, FR, NL, BE, ES, PT, IT, CH, AT, SE, NO, DK, FI, PL, IN, SG, JP, PH, AU, NZ, AE, IL, ZA, BR, MX and AR. For anywhere else, type a location or paste a search URL with its geoId. Postings come in the language the employer wrote them. Keyword matching works on any alphabet; the built-in synonyms (RN for nurse, dev for developer) are English only.

#### Can I paste a LinkedIn search URL with my own filters?

Yes. URLs from linkedin.com/jobs/search and paths like /jobs/python-jobs-toronto work. These parameters are passed to LinkedIn: keywords, location, geoId, f_TPR, f_JT, f_E, f_WT, f_C, f_I, f_SB2, f_AL, distance and sortBy; others are ignored. A URL needs keywords, a location or a geoId. Only keyword relevance is re-checked on URL results.

#### What do posted_date, applicants and salary_text contain?

`posted_date` is a date only (YYYY-MM-DD) from the search card; LinkedIn shows no time. `posted_ago` is LinkedIn's relative text such as '1 month ago'. `applicants` is the count text as shown, e.g. 'Over 200 applicants'. `salary_text` is the pay text exactly as LinkedIn displays it, e.g. 'CA$68,600.00/yr - CA$91,500.00/yr', and is not split into numbers. `countries` is detected from the location text.

### Lawful use

- B2B use only: recruiter and poster names are never collected, but a description can still carry a company mailbox or a contact the employer wrote into the posting. That is business contact information; use it only for business purposes such as job search, hiring-market research or a relevant business enquiry, never for consumer marketing.
- No spam: contact people only with relevant, individual business messages, identify yourself, and honour every opt-out at once. Bulk unsolicited email built from this data is not allowed.
- You are responsible for complying with the anti-spam and privacy laws that apply to you and to the people you contact, including Canada's CASL, the US CAN-SPAM Act and the EU/UK GDPR (lawful basis, transparency, the right to object).
- Removal requests: open an issue on this Actor's Issues tab naming the person, email address or domain to remove. It is added to our suppression list and honoured within 7 days; from then on matching records are not returned.
- Recruiter and poster cards are never read; personal emails are removed from descriptions.

### Limits (stated honestly)

- LinkedIn shows at most about 1,000 jobs per search; split broad searches by keyword or location.
- The Actor always uses Apify's datacenter proxy; there is no residential option. LinkedIn rate-limits datacenter addresses, so big runs can stop early (the status message says which searches did).
- Keywords match whole words with simple plurals, a few synonyms (nurse: RN, LPN, LVN; engineer: eng; developer: dev, programmer) and, in titles, a shared stem of 5+ letters ('actuary' finds 'Actuarial'). With details off only the title is checked, so postings whose title does not relate are skipped.
- Posted date is a date only; LinkedIn shows no time.
- Salary appears only where LinkedIn displays it on the public page.
- Workplace type (remote/hybrid/on-site) is sent to LinkedIn as a filter but cannot be re-checked, because the public page does not show it.
- Search URLs are used as they are: their own filters go to LinkedIn, and only keyword relevance is re-checked on their results (not country, date, job type or level).
- LinkedIn can change its public pages; the daily health run catches breakage within 24 hours.

### Related Aurelix tools

Public Aurelix Actors, grouped by the data they collect. All are pay-per-result and need no login.

#### Jobs and hiring data

- **[Greenhouse Jobs Scraper](https://apify.com/aurelix/greenhouse-jobs-scraper)**: Live jobs from a company's Greenhouse, Lever, Ashby or SmartRecruiters board, with salary and Canadian province tags.

#### E-commerce and product data

- **[AliExpress Scraper](https://apify.com/aurelix/aliexpress-product-search)**: AliExpress search results by keyword: price, discount, rating, units sold, ship-from country and sponsored flag.
- **[Amazon Best Sellers Scraper](https://apify.com/aurelix/amazon-best-sellers)**: Amazon Best Sellers and New Releases top 100 on 10 marketplaces: rank, ASIN, price, rating, rank change.

#### Leads and company data

- **[Google Maps Business Scraper](https://apify.com/aurelix/google-maps-scraper)**: Local business lists from Google Maps: phones, websites, ratings, hours, coordinates; optional website emails and socials.
- **[Recently Funded Companies](https://apify.com/aurelix/recently-funded-companies)**: US companies that just filed an SEC Form D: amount raised, industry, state, executives, confirmed website.

#### Ad intelligence

- **[Facebook Ad Library Scraper](https://apify.com/aurelix/facebook-ad-library-scraper)**: Facebook and Instagram business ads from the Meta Ad Library: copy, creatives, landing pages, dates, optional EU reach.

#### Canada and government data

- **[Canada Building Permits Scraper](https://apify.com/aurelix/canada-building-permits-scraper)**: Building permits and development applications from 7 Canadian cities: address, type, status, dates, value, contractor company.

#### AI, content and SEO

- **[Google Trends Scraper](https://apify.com/aurelix/google-trends-scraper)**: Google Trends interest over time, by region and rising queries for any number of keywords, plus trending searches.
- **[Website to Markdown Crawler](https://apify.com/aurelix/website-to-markdown)**: Crawls a site and returns one row of clean main-content Markdown per page, with title, headings and links.

### Recent changes

- **0.1**: Lower price scheduled: $0.50 per 1,000 jobs on the free plan and $0.40 on paid plans, with the start fee per run rising from $0.00005 to $0.0005; $1.50 and $1.05 apply until then.

The full history is on the **Changelog** tab.

### Tested daily

An automated health check runs this Actor every day on a fixed input and checks that at least 4 jobs come back with `job_id`, `title`, `company`, `job_url`, `posted_date`, `employment_type` filled in; a failed check alerts the maintainer straight away.

### Your feedback

Missing a field, found a bug or need another filter? Open an issue on the **Issues** tab; we aim to answer within a day. If this Actor saved you time, a short review helps other people find it.

# Changelog

This Actor's version history is a separate document: https://apify.com/aurelix/linkedin-jobs/changelog.md

# Actor input Schema

## `keywords` (type: `array`):

One search per entry, e.g. \['data engineer', 'nurse']. Combined with the country, location and filters below.

## `country` (type: `string`):

Restrict to one country using LinkedIn's exact country id (not fuzzy text), and drop any result whose location names another country. Empty = no country restriction.

## `location` (type: `string`):

City or region as typed on LinkedIn, e.g. 'Toronto, Ontario, Canada'. With a country set, the country stays the hard filter.

## `datePosted` (type: `string`):

Only jobs posted within this window. Results are re-checked against the posted date.

## `jobTypes` (type: `array`):

Any of: fullTime, partTime, contract, temporary, internship, volunteer, other. Empty = all. Results are re-checked against the posting's employment type.

## `experienceLevels` (type: `array`):

Any of: internship, entry, associate, midSenior, director, executive. Empty = all. Results are re-checked against the posting's seniority level.

## `workplaceTypes` (type: `array`):

Any of: onsite, remote, hybrid. Empty = all.

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

'recent' = newest first; 'relevant' = LinkedIn's relevance order.

## `searchUrls` (type: `array`):

Search URLs copied from linkedin.com/jobs/search, e.g. 'https://www.linkedin.com/jobs/search/?keywords=python\&geoId=101174742\&f_TPR=r604800'. Their own filters are used as they are.

## `maxResultsPerSearch` (type: `integer`):

Exact upper limit of jobs returned for each keyword or URL. LinkedIn shows at most about 1,000 jobs per search.

## `includeDetails` (type: `boolean`):

Open each job's public page for description, seniority, employment type, function and industries. Turn off for a faster, cheaper list of title, company, location, date and link only.

## `incremental` (type: `boolean`):

Return only jobs not returned by a previous run with the same searches. Use with a schedule for a daily feed.

## `stateKey` (type: `string`):

Name for the 'new since last run' memory. Leave empty to derive it from the searches.

## `slackWebhookUrl` (type: `string`):

After each run, post a short digest to Slack: how many results were saved (new ones only when 'Only new jobs since last run' is on) and the top 10 with links, e.g. https://hooks.slack.com/services/T000/B000/XXXX. Nothing is posted when the run saved nothing. Leave empty to skip.

## `webhookUrl` (type: `string`):

After each run, POST the same digest as JSON (actor, newOnly, count, items = top 10 results, runUrl, text) to any URL, e.g. a Zapier, Make or n8n webhook. Nothing is sent when the run saved nothing. Leave empty to skip.

## Actor input object example

```json
{
  "keywords": [
    "data engineer"
  ],
  "country": "",
  "location": "",
  "datePosted": "any",
  "jobTypes": [],
  "experienceLevels": [],
  "workplaceTypes": [],
  "sortBy": "recent",
  "searchUrls": [],
  "maxResultsPerSearch": 10,
  "includeDetails": true,
  "incremental": false
}
```

# Actor output Schema

## `jobs` (type: `string`):

All public LinkedIn job postings found in this run, one item per job.

# 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 = {
    "keywords": [
        "data engineer"
    ],
    "maxResultsPerSearch": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("aurelix/linkedin-jobs").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 = {
    "keywords": ["data engineer"],
    "maxResultsPerSearch": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("aurelix/linkedin-jobs").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 '{
  "keywords": [
    "data engineer"
  ],
  "maxResultsPerSearch": 10
}' |
apify call aurelix/linkedin-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aurelix/linkedin-jobs"
        }
    }
}
```

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/AbVuu9LNiPfGWwzqY/builds/SiQZbb9bRWwXJRQDV/openapi.json
