# LinkedIn Job Listings Scraper: CSV Export & New Job Alerts (`neverempty/linkedin-job-listings-monitor`) Actor

For recruiters, job seekers and sales leads: LinkedIn jobs with your words in the title and a checked posting date in your 24h/week/month window, with salary, applicants, description. On 2026-10-13 a 24h search kept 300, dropped 147 non-matching jobs unbilled. New-job alerts. CSV, Excel, no login.

- **URL**: https://apify.com/neverempty/linkedin-job-listings-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 3 total users, 2 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 job returneds

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

## LinkedIn Job Listings Scraper: CSV Export & New Job Alerts

**For recruiters, job seekers and sales teams tracking who is hiring: LinkedIn jobs that have your words in the title, with every posting date checked against the 24-hour, week or month window you pick, as spreadsheet rows.** Search by job title, location, date posted or company (or paste a LinkedIn job search URL) and get title, company, company URL, location, posting date, salary, applicants and the full job description, ready to download as CSV, Excel or JSON.

LinkedIn mixes loosely related jobs into its results. On 2026-10-13 a past-24-hours search for `data engineer` in the United States returned 300 jobs with those words in the title and removed 147 others before anything was charged. Monitor mode remembers what it already gave you, so an hourly or daily schedule returns only jobs that are new since the last run: a LinkedIn job alert for Google Sheets, Slack, a CRM or your own code. No LinkedIn account, no cookies.

### What you get

- **Only jobs that match your words, on by default**: every job whose title does not contain all the words of your search term is removed before it is charged, and the log says how many. Each row also has `titleMatchesSearch`, so you can switch the check off and filter later.
- **Only jobs from the date window you picked**: with "Past 24 hours", "Past week" or "Past month", the posting date of every job is checked again before it is returned. A job that is clearly older is left out and not charged.
- **Every job as one clean row**: job ID, title, company, company LinkedIn URL, company logo, location, posting date (the date LinkedIn shows), salary when the job shows one, link to the job.
- **Full job details (optional)**: full description with paragraphs and bullet points, number of applicants as LinkedIn shows it, employment type, seniority level, job function and industries.
- **Only new jobs (monitor mode)**: each run returns jobs not returned before and posted around or after the last check. In a test on 2026-10-13, a second check of `data engineer` in the United States, started five minutes after the first, found 131 new jobs. Jobs that did not fit into one run (max results or your spending limit) come first in the next run.
- **Export anywhere**: download every run as CSV, Excel, JSON or XML, or send it to Google Sheets, Slack, Zapier, Make or your own code through the Apify API.
- **No LinkedIn account, no cookies**: it reads the public job pages LinkedIn shows to signed-out visitors, so your own account is never involved.

### Who uses it

- **Recruiters and staffing agencies**: daily lists of companies hiring for the roles you place, with the company LinkedIn URL.
- **Job seekers and career coaches**: an hourly or daily alert for exact titles in exact places, with the loosely related jobs already removed.
- **Sales and lead generation**: companies that are hiring now, by role, location and company (hiring signals for outreach).
- **Researchers and analysts**: job market data by title, location, salary, seniority and industry.
- **AI agents and job-matching apps**: clean rows with the full description, ready for an LLM to rank, summarise or match against a CV.

### How to use it

1. Type one or more job titles (for example `data engineer`) and locations (for example `United States`, `Germany`, `London`).
2. Pick how recent the jobs must be (past 24 hours, week or month).
3. Set **Max jobs per search** and turn on **Include job details** if you want the description and applicants.
4. For alerts, turn on **Monitor mode: only new jobs** and schedule the Actor. Run broad searches (a common title across a whole country) **hourly**, and narrow ones (one city, one company, a rare title) daily.

Or paste the address of a LinkedIn job search into **LinkedIn job search URLs**, for example a search for one company's jobs.

#### Input fields

| Field | What it does |
|---|---|
| `searchQueries` | Job titles or keywords, one per line. Each is searched in every location. |
| `locations` | Countries, regions or cities, one per line. Empty searches worldwide. |
| `postedWithin` | `24h`, `week`, `month` or `any`. The posting date of every job is checked again. |
| `searchUrls` | LinkedIn job search addresses, for example one company's jobs. |
| `titleMustMatch` | On by default: only jobs whose title has every word of the search term. |
| `includeJobDetails` | Adds description, applicants, employment type, seniority, job function and industries. |
| `maxResultsPerSearch` | Jobs per search. Empty means 100. LinkedIn lists up to 1,000 jobs for one search. |
| `onlyNew` | Monitor mode: only jobs not returned by earlier runs. |
| `watchName` | Keeps separate monitor memories for the same search. |
| `resetMonitoringState` | Starts a monitor over, as if it were the first run. |

#### Example input

```json
{
  "searchQueries": ["data engineer"],
  "locations": ["United States"],
  "postedWithin": "week",
  "titleMustMatch": true,
  "includeJobDetails": true,
  "maxResultsPerSearch": 100
}
```

#### Example output

```json
{
  "status": "ok",
  "jobId": "4455981524",
  "title": "Registered Nurse - Mental Health Older Adult - Days",
  "company": "Methodist Health System",
  "companyUrl": "https://www.linkedin.com/company/methodist-health-system",
  "location": "Richardson, TX",
  "postedDate": "2026-10-05",
  "postedAgo": "1 week ago",
  "applicants": "Be among the first 25 applicants",
  "salary": null,
  "employmentType": "Full-time",
  "seniorityLevel": "Not Applicable",
  "industries": "Hospitals and Health Care",
  "description": "Hours of Work: 7am to 7pm ...",
  "titleMatchesSearch": true,
  "url": "https://www.linkedin.com/jobs/view/4455981524/"
}
```

### Pricing

Pay per result: **$1.50 per 1,000 jobs** on the free plan (less on paid Apify plans), plus a run start fee of **$0.001**. Rows with full job details (description, applicants, criteria) are **$2.00 per 1,000** on the free plan (less on paid plans). Rows that only explain something (no jobs found, nothing new, a page that could not be read) are free. You can set a maximum charge per run in Apify; the Actor stops there and tells you.

### FAQ

**How do I scrape LinkedIn jobs without logging in?**
Run this Actor with a job title and a location. It reads the job pages LinkedIn shows to signed-out visitors, so you do not give it any account or cookie.

**How do I get a daily alert of new LinkedIn jobs?**
Turn on monitor mode and schedule the Actor daily. Each run returns only jobs that are new since the last run; connect the dataset to Google Sheets, Slack, Zapier or Make.

**Can I export LinkedIn jobs to Excel or CSV?**
Yes. Every run's dataset downloads as CSV, Excel, JSON or XML from the Storage tab, or through the Apify API.

**How often should I run a LinkedIn job alert?**
Hourly for broad searches, such as a common title across a whole country: each check reads the jobs LinkedIn lists since the last one, and an hourly schedule keeps that list short, so new jobs are not crowded out. Daily is enough for a city, one company or a rare title.

**Can I get LinkedIn jobs posted in the last 24 hours only?**
Yes. Pick "Past 24 hours". LinkedIn's own date filter is used, and the posting date of every job is checked again before it is returned, so a job that is clearly older is left out and not charged.

**How do I get only LinkedIn jobs that match my job title?**
Keep `titleMustMatch` on (the default). LinkedIn adds loosely related jobs to its results; this Actor removes every job whose title does not contain all your words before anything is charged, and the log says how many were removed.

**Why do I get fewer jobs than LinkedIn shows?**
Because the jobs without your words in the title were removed (and not charged). Turn `titleMustMatch` off to get everything LinkedIn lists; the column `titleMatchesSearch` still marks which jobs match.

**Can I scrape all jobs of one company on LinkedIn?**
Yes. Open the company's jobs on LinkedIn, copy the address of that search and paste it into **LinkedIn job search URLs**. The company filter is used, together with keywords, location and posted date.

### Good to know

- LinkedIn shows at most 1,000 jobs for one search; for more, split the search by city or by posting date.
- LinkedIn does not apply its workplace type, job type, experience level or salary filters to signed-out visitors, so this Actor does not offer them (search URLs with those filters are not accepted, so you never pay for unfiltered jobs). Posted date, location and company filters work.
- The posting date is the date LinkedIn shows on the job card (a day, not a time of day). The 24-hour check keeps any job whose date can still be within the last 24 hours in some time zone.
- Number of applicants is LinkedIn's own wording ("Over 200 applicants", "Be among the first 25 applicants").
- Salary appears only on jobs where the employer shows one.
- Recruiter names and contact details are not collected; e-mail addresses and phone numbers inside descriptions are replaced with `[email removed]` / `[phone removed]`.
- If LinkedIn refuses a request, the Actor asks again from another IP address. If LinkedIn shows a check page or its sign-in wall, the Actor stops there instead of working around it, and the rows already read are returned.
- Monitor memory is stored per search and `watchName` in your Apify account. Each check reads up to 1,000 jobs LinkedIn lists since the last check, so very broad searches are best run hourly.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

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

What to search for, one per line, for example data engineer or nurse. Each one is searched in every location below. Leave empty to search only by location or by the search URLs.

## `locations` (type: `array`):

Where to search, one per line, as you would type it on LinkedIn: a country, region or city such as United States, Germany or London. Leave empty to search worldwide.

## `postedWithin` (type: `string`):

Only jobs posted in this window. The posting date of every job is checked again before it is returned: a job that is clearly older than the window is not returned and not charged. Empty means any time.

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

Optional. Paste the address of a LinkedIn job search (linkedin.com/jobs/search/?keywords=...\&location=...). Keywords, location, posted date and company filters are used. Each URL is one more search.

## `titleMustMatch` (type: `boolean`):

On by default: return only jobs whose title contains every word of the search term (case does not matter), so loosely related jobs LinkedIn adds are removed before anything is charged. Off: return everything LinkedIn lists for the search.

## `includeJobDetails` (type: `boolean`):

On: also open each job and add the full description, number of applicants, employment type, seniority level, job function and industries. Off: the search card fields only (faster).

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

Stop each search after this many jobs (1 to 1000; LinkedIn lists up to 1000 jobs for one search). Empty means 100.

## `onlyNew` (type: `boolean`):

On: each run returns only jobs that were not returned by an earlier run of the same search and watch name and were posted around or after the last check. The first run returns jobs and remembers them. Schedule the Actor (hourly or daily) for job alerts.

## `watchName` (type: `string`):

Optional. A name for this monitor (letters, digits, dot, dash, underscore). Use different names to keep separate memories for the same search. Empty uses one shared memory per search.

## `resetMonitoringState` (type: `boolean`):

On: forget what this watch has already returned, so this run is a first check again. Off by default.

## Actor input object example

```json
{
  "searchQueries": [
    "data engineer"
  ],
  "locations": [
    "United States"
  ],
  "postedWithin": "week",
  "titleMustMatch": true,
  "includeJobDetails": false,
  "maxResultsPerSearch": 20,
  "onlyNew": false,
  "resetMonitoringState": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per LinkedIn job: job ID, title, company, company URL, location, posting date, salary (when shown), link and position in the search. With job details: full description, applicants, employment type, seniority level, job function and industries. Monitor mode marks rows first-check or new. A search with no jobs, nothing new, a refused request or a run that hit its maximum charge comes back as a free row that says why.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "data engineer"
    ],
    "locations": [
        "United States"
    ],
    "postedWithin": "week",
    "maxResultsPerSearch": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/linkedin-job-listings-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": ["data engineer"],
    "locations": ["United States"],
    "postedWithin": "week",
    "maxResultsPerSearch": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/linkedin-job-listings-monitor").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 '{
  "searchQueries": [
    "data engineer"
  ],
  "locations": [
    "United States"
  ],
  "postedWithin": "week",
  "maxResultsPerSearch": 20
}' |
apify call neverempty/linkedin-job-listings-monitor --silent --output-dataset

```

## MCP server setup

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

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/vRaOcD4Ak6uxj3GCN/builds/MXaRvR3qslfmFpY1s/openapi.json
