# LinkedIn Jobs Scraper — Never Pay for Blocked Pages (`0xgollum/reliable-linkedin-jobs`) Actor

Search LinkedIn job postings by keywords, location, workplace type and date - no login required. Pulls title, company, location, seniority, employment type, applicants and description. Optional Greenhouse/Lever add-on. A job is only billed if it returned real data.

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

## Pricing

from $20.00 / 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

## Reliable LinkedIn Jobs

Search LinkedIn job postings by keywords, location, workplace type (on-site/remote/hybrid) and
posting date — no cookies, no login, no LinkedIn account required.

### What you get

For each matching job:

- Title, company, location, posting date, direct URL
- Seniority level, employment type, job function, industries, applicant count
- Full job description (capped at 3000 characters — see Limits below)

Optionally, also pull jobs directly from a target company's **Greenhouse** or **Lever** board —
a useful complement when you already know which companies to watch, not an open discovery tool.

### Why "Reliable"

LinkedIn blocks automated requests with a non-standard `999` status code — not a 403 or 429 — and
does it regardless of proxy unless the request first "warms up" a real session (visitor cookies +
full browser headers + a referer chain). This actor does that warm-up on every proxy identity it
uses, and rotates to a fresh identity (up to `max_proxy_sessions`, default 3) if one gets blocked
— retrying the *same* page rather than skipping ahead or restarting the search.

**A job is only ever pushed to the dataset — and only ever billed — if it actually carries real
data.** If a search page is blocked on every session, the run simply returns fewer jobs; it never
fabricates placeholder rows. If a job's detail page is blocked after its search-result row already
parsed successfully (proof the job is real), that job is still pushed with the detail fields left
empty — a partial result beats discarding an otherwise-real job.

### Input

| Field | Description |
|---|---|
| `keywords` | Job title / skills to search for (required). |
| `location` | City, country, or "Remote". Leave empty to search worldwide. |
| `workplace_type` | `any` / `onsite` / `remote` / `hybrid`. |
| `posted_within` | `any` / `day` / `week` / `month`. |
| `max_jobs` | Stop the LinkedIn search once this many results are collected (default 25). |
| `fetch_details` | Fetch each job's detail page for richer data (default true). |
| `greenhouse_boards` | Optional list of Greenhouse board tokens (e.g. `stripe`). |
| `lever_boards` | Optional list of Lever board tokens (e.g. `palantir`). |
| `max_proxy_sessions` | How many fresh proxy identities to try per blocked page/job (default 3). |
| `proxyConfiguration` | Residential proxy strongly recommended. |

### Limits (honest, not hidden)

- Some recruiters paste raw HTML (application forms, phone-country dropdowns) directly into the
  description field. There's no reliable way to separate that from real description text, so
  descriptions are capped at 3000 characters rather than risk shipping thousands of characters of
  noise.
- Greenhouse/Lever are account-based: you supply the company tokens to check. This actor does not
  discover which companies use which ATS.

# Actor input Schema

## `keywords` (type: `string`):

Job title / skills to search for on LinkedIn Jobs.

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

City, country, or 'Remote'. Leave empty to search worldwide.

## `workplace_type` (type: `string`):

Filter by LinkedIn's declared workplace type for the posting.

## `posted_within` (type: `string`):

Only include jobs posted within this time window.

## `max_jobs` (type: `integer`):

Stop the LinkedIn search once this many results have been collected.

## `fetch_details` (type: `boolean`):

For each LinkedIn result, also fetch its detail page (seniority, employment type, applicant count, full description). Slower, more requests, richer data.

## `greenhouse_boards` (type: `array`):

Company Greenhouse board tokens to include alongside the LinkedIn search (e.g. 'stripe' for boards.greenhouse.io/stripe). Account-based, not open discovery.

## `lever_boards` (type: `array`):

Company Lever board tokens to include alongside the LinkedIn search (e.g. 'netflix' for jobs.lever.co/netflix).

## `max_proxy_sessions` (type: `integer`):

If LinkedIn blocks one proxy identity, retry with a fresh one, up to this many times, before giving up on that page or job detail.

## `proxyConfiguration` (type: `object`):

Residential proxy strongly recommended - LinkedIn aggressively blocks datacenter IPs.

## Actor input object example

```json
{
  "keywords": "python developer",
  "location": "Remote",
  "workplace_type": "any",
  "posted_within": "any",
  "max_jobs": 25,
  "fetch_details": true,
  "greenhouse_boards": [],
  "lever_boards": [],
  "max_proxy_sessions": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "keywords": "python developer",
    "location": "Remote"
};

// Run the Actor and wait for it to finish
const run = await client.actor("0xgollum/reliable-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": "python developer",
    "location": "Remote",
}

# Run the Actor and wait for it to finish
run = client.actor("0xgollum/reliable-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": "python developer",
  "location": "Remote"
}' |
apify call 0xgollum/reliable-linkedin-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,0xgollum/reliable-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/uUMxqIWDbpTHz5jLc/builds/3bDhMQ2A8rgnt3qgI/openapi.json
