# LinkedIn Jobs Scraper (No Cookies or Login Required) (`curly/linkedin-jobs-scraper`) Actor

Scrape LinkedIn jobs by company, location, and keyword. Get descriptions, salary, applicants, criteria, and apply URLs with no proxy setup. ($0.50 USD per 1,000 results)

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

## Pricing

$0.50 / 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.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LinkedIn Jobs Scraper (No Cookies or Login Required)

Scrape LinkedIn job listings by company, location, and job title or keyword. Get structured job descriptions, salary data, criteria, applicant counts, workplace type, and application information without LinkedIn cookies or login.

Proxy access and retry handling are included. You only choose what jobs you want.

### Quick start

1. Paste one LinkedIn company URL or slug per line. A slug is the part after `/company/` in a LinkedIn URL—for example, `openai`.
2. Optionally choose locations, titles or keywords, posting age, result limit, sort order, and detail enrichment.
3. Click **Start** and download the results.

Only the company field is required. Every other field has a ready-to-use default.

#### Minimal input

```json
{
  "companies": [
    "https://www.linkedin.com/company/openai"
  ]
}
```

#### Filtered search

```json
{
  "companies": ["openai", "microsoft"],
  "locations": ["Germany", "Remote"],
  "jobTitles": ["Software Engineer"],
  "maxResultsPerUrl": 10,
  "postedLimit": "week",
  "sortBy": "date",
  "includeDetails": true
}
```

### Input options

| Field | Required | What it does |
| --- | --- | --- |
| `companies` | Yes | LinkedIn company URLs or slugs. Up to 100. |
| `locations` | No | Up to 10 locations such as `Germany`, `Berlin`, or `Remote`. Leave empty to apply no location filter. |
| `jobTitles` | No | Up to 10 job titles or keywords such as `Software Engineer`. Leave empty to include every available role. |
| `maxResultsPerUrl` | No | Maximum unique jobs returned for each company URL or slug, from 1 to 100. Default: `10`. |
| `postedLimit` | No | Jobs from the past hour, 24 hours, week, month, or any time. Default: past month. |
| `sortBy` | No | Show the newest jobs first or use LinkedIn's relevance order. Default: newest first. |
| `includeDetails` | No | Keep enabled for full descriptions and enriched fields. Disable for faster basic results. Default: enabled. |

Company URLs from localized LinkedIn domains such as `de.linkedin.com` are accepted and normalized automatically. The result limit applies separately to every company URL or slug and covers all filter combinations for that company. Duplicate companies and jobs are returned once.

Every company, location, and title is combined into a search. A run can contain up to 100 such search combinations. For example, 2 companies × 2 locations × 3 titles creates 12 searches.

Company resolution, job discovery, and detail enrichment use bounded parallel processing. Completed job records are written progressively instead of waiting for the entire batch to finish.

### What you get

Each dataset item represents one unique LinkedIn job and can include:

- Job ID, canonical LinkedIn URL, title, company, and location
- Publication and expiration dates
- Clean plain-text job descriptions
- Employment type, seniority, job functions, and industries
- Structured salary range, currency, period, and salary type
- Applicant count with exact or boundary semantics
- Remote, hybrid, or on-site workplace type
- External application URL or Easy Apply status
- The location and keyword that found the job
- Detail enrichment status

Example result:

```json
{
  "job_id": "4250000000",
  "job_url": "https://www.linkedin.com/jobs/view/4250000000",
  "title": "Software Engineer",
  "company_name": "OpenAI",
  "company_id": "11130470",
  "company_url": "https://www.linkedin.com/company/openai",
  "company_slug": "openai",
  "location": "San Francisco, CA",
  "published_at": "2026-07-25",
  "description": "Build reliable systems for advanced AI products.",
  "employment_type": "Full-time",
  "seniority_level": "Mid-Senior level",
  "job_functions": ["Engineering", "Information Technology"],
  "industries": ["Software Development"],
  "salary": {
    "text": "$180,000–$240,000/yr",
    "min": 180000,
    "max": 240000,
    "currency": "USD",
    "period": "year",
    "type": "base"
  },
  "applicants": {
    "count": 200,
    "count_type": "minimum",
    "text": "Over 200 applicants"
  },
  "expires_at": "2026-08-25",
  "benefits": null,
  "workplace_type": "hybrid",
  "application": {
    "type": "external",
    "url": "https://jobs.example.com/apply/4250000000",
    "login_required": false
  },
  "search_location": "San Francisco",
  "search_keyword": "Software Engineer",
  "details_status": "complete",
  "scraped_at": "2026-07-28T12:00:00.000Z",
  "source": "linkedin_job"
}
```

Unavailable public values are returned as `null` or an empty array instead of being guessed. If `includeDetails` is `false`, detail-only fields stay empty and `details_status` is `not_requested`.

### Price

The price is **$0.0005 per stored job** — **$0.50 per 1,000 results**. You pay for returned dataset items, not failed searches or duplicate jobs.

### Run with the API

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/curly~linkedin-jobs-scraper/run-sync-get-dataset-items?format=json" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "companies": ["openai"],
    "locations": ["Germany"],
    "jobTitles": ["Software Engineer"],
    "maxResultsPerUrl": 10,
    "postedLimit": "month",
    "sortBy": "date",
    "includeDetails": true
  }'
```

The same input works with the Apify API client, schedules, webhooks, and integrations, making the Actor usable as a LinkedIn job search API.

Existing API integrations that send the former `maxItems` field remain supported. That deprecated field keeps its original global-cap behavior, but new integrations should use `maxResultsPerUrl`.

### Limits and responsible use

- Results depend on jobs visible through LinkedIn's public no-login pages.
- Job details can disappear after a listing closes or changes.
- LinkedIn may omit salary, applicants, workplace type, application URL, or other fields.
- Use the Actor only for lawful purposes and comply with applicable privacy, employment, data protection, and platform rules.

### FAQ

#### Do I need LinkedIn cookies or an account?

No. The Actor uses public LinkedIn pages and does not ask for your LinkedIn credentials.

#### Do I need to configure a proxy?

No. Proxy access is included and configured automatically.

#### Can I search worldwide?

Yes. Leave `locations` empty to apply no location filter for the selected companies.

#### Can I limit the jobs returned from each company?

Yes. Set **Maximum results per URL** from 1 to 100. For example, a value of `10` returns at most 10 unique jobs for each company URL or slug, even when you select multiple locations or job-title filters.

#### What does “Include job details” change?

When enabled, the Actor visits each job page to enrich the search result with descriptions, criteria, salary, applicants, workplace type, expiration, and application metadata. Disable it for a faster lightweight listing search.

#### Why is a field `null`?

LinkedIn does not publish every field for every job. Missing values remain explicit rather than being inferred.

# Actor input Schema

## `companies` (type: `array`):

Paste one company page URL or slug per line. A slug is the part after /company/ (for example, openai). Duplicate companies are processed once.

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

Optional: enter up to 10 locations, one per line, such as Germany, Berlin, or Remote. Leave empty to apply no location filter.

## `jobTitles` (type: `array`):

Optional: enter up to 10 job titles or keywords, one per line. Leave empty to include every available role.

## `maxResultsPerUrl` (type: `integer`):

Maximum number of unique jobs returned for each company URL or slug, across all selected location and title filters.

## `maxItems` (type: `integer`):

Deprecated compatibility field for existing API integrations.

## `postedLimit` (type: `string`):

Only return jobs posted during this period.

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

Show the newest jobs first or use LinkedIn's relevance order.

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

Keep enabled for full descriptions, criteria, pay, applicants, and application data. Disable for faster basic results.

## Actor input object example

```json
{
  "companies": [
    "https://www.linkedin.com/company/openai"
  ],
  "locations": [],
  "jobTitles": [],
  "maxResultsPerUrl": 10,
  "postedLimit": "month",
  "sortBy": "date",
  "includeDetails": true
}
```

# Actor output Schema

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

No description

## `runSummary` (type: `string`):

No description

## `failedInputs` (type: `string`):

No description

## `failedTargets` (type: `string`):

No description

# 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 = {
    "companies": [
        "https://www.linkedin.com/company/openai"
    ],
    "locations": [],
    "jobTitles": [],
    "maxResultsPerUrl": 10,
    "postedLimit": "month",
    "sortBy": "date",
    "includeDetails": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("curly/linkedin-jobs-scraper").call(input);

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

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

```

## Python example

```python
from apify_client import ApifyClient

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

# Prepare the Actor input
run_input = {
    "companies": ["https://www.linkedin.com/company/openai"],
    "locations": [],
    "jobTitles": [],
    "maxResultsPerUrl": 10,
    "postedLimit": "month",
    "sortBy": "date",
    "includeDetails": True,
}

# Run the Actor and wait for it to finish
run = client.actor("curly/linkedin-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "companies": [
    "https://www.linkedin.com/company/openai"
  ],
  "locations": [],
  "jobTitles": [],
  "maxResultsPerUrl": 10,
  "postedLimit": "month",
  "sortBy": "date",
  "includeDetails": true
}' |
apify call curly/linkedin-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=curly/linkedin-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/4oeeqRK8vuZLdESiY/builds/JACfCRDWJ6CAolMGs/openapi.json
