# LinkedIn Job Postings API — Public Hiring Data (`nexgenwatch/linkedin-job-postings-api`) Actor

Query public LinkedIn job postings by role, location, employment type, and posting age. Receive normalized records through an Apify dataset or API. Public job postings only; no accounts, profiles, or people data. Pay per delivered record.

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

## Pricing

from $33.50 / 1,000 public job postings

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/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 Job Postings API — Public Hiring Data

Query public LinkedIn job postings and receive normalized hiring records through an Apify dataset or API response. This actor is for recruiting, hiring-intelligence, and labour-market workflows that need repeatable structured records rather than manual browsing.

### What it delivers

- One structured record per public posting, keyed by LinkedIn's numeric `job_id`.
- Role title, hiring organisation, place, posting date, salary text when published, and the public posting URL.
- Optional public description retrieval with an explicit `description_status`.
- Source URL and UTC `observed_at` provenance on every record.
- A bounded 500-record maximum and fail-loud handling for blocks, throttling, source-shape loss, and time-budget exhaustion.

This actor reads public logged-out job-posting pages only. It does not use accounts, cookies, profiles, people records, applicant data, or authenticated LinkedIn surfaces.

### Pricing

Pay per delivered record. The record is pushed to the dataset before its charge fires.

| Event | Unit | FREE | BRONZE | SILVER | GOLD / PLATINUM / DIAMOND |
|---|---|---:|---:|---:|---:|
| `apify-actor-start` | Run start | $0.02 | $0.02 | $0.02 | $0.02 |
| `job_record` | Public job posting delivered | $0.05 | $0.045 | $0.04 | $0.0335 |

Worked example: 200 delivered public postings cost $0.02 + (200 × $0.05) = **$10.02** on the base customer tier. Empty, blocked, or undelivered records never trigger `job_record`.

### Input

```json
{
  "keywords": "data engineer",
  "location": "United States",
  "jobType": "full-time",
  "datePosted": "past-week",
  "maxResults": 100,
  "fetchDescriptions": false,
  "watchMode": false
}
```

The supplied store prefill requests five recent records and normally completes in well under five minutes. `maxResults` cannot exceed 500.

### Sample output

```json
{
  "job_id": "4425881907",
  "title": "Data Engineer",
  "company": "Example Cloud",
  "location": "United States",
  "posted_at": "2026-08-12",
  "job_url": "https://www.linkedin.com/jobs/view/data-engineer-at-example-4425881907",
  "salary_text": "$120k-$150k",
  "employment_type": "full-time",
  "description": null,
  "description_status": "not_requested",
  "change_type": null,
  "changed_fields": [],
  "first_seen": null,
  "detected_at": null,
  "source_url": "https://www.linkedin.com/jobs/view/data-engineer-at-example-4425881907",
  "observed_at": "2026-08-12T17:14:17Z",
  "query": "data engineer"
}
```

### Delta mode

Set `watchMode` to `true` and schedule stateless runs. The first run writes a KV baseline and emits zero alerts. Later runs deliver only newly seen postings, changed postings, and postings absent from the public result window on two consecutive eligible runs. The source-native composite key is `job_id`; a maximum of 500 deltas can be delivered in one run.

Delta mode stores only its bounded baseline in a named KV store. It does not run an always-on process. A partial source read never commits a new baseline.

### API, CLI, and MCP

API:

```bash
curl -X POST "https://api.apify.com/v2/acts/nexgenwatch~linkedin-job-postings-api/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords":"data engineer","location":"United States","maxResults":100}'
```

CLI:

```bash
apify call nexgenwatch/linkedin-job-postings-api -p '{"keywords":"data engineer","maxResults":100}'
```

MCP: expose this actor through Apify's Actor tools and ask an agent to call `nexgenwatch/linkedin-job-postings-api` with the same JSON input. The output remains the default Apify dataset; no agent receives broader source access.

### Use with

`linkedin-job-postings-api` → company/domain enrichment → hiring-intensity analysis → scheduled delta runs. Keep downstream enrichment on company-level public facts; this actor supplies no personal profiles or applicant data.

### Honest limits

- LinkedIn can throttle, block, or change its public guest-posting HTML without notice. A blocked first page fails loudly and bills no `job_record`; a later block retains delivered rows and labels the run `PARTIAL`.
- Public result windows are not a complete census of all jobs. Ranking and availability can vary by place, query, and time.
- Salary, description, and employment type can be absent because the source did not publish them.
- `removed_from_public_search` means a posting disappeared from this public query twice; it is not proof that the employer closed the requisition.
- The exact-host robots policy is re-read every run. This actor proceeds under Steve's recorded one-actor source ruling dated 2026-08-12; it never defeats a login, CAPTCHA, WAF, or paywall.

### FAQ

**Does this actor access LinkedIn profiles or people data?** No. It is limited to public logged-out job postings.

**Does it require my LinkedIn account?** No account, cookie, credential, or authenticated surface is accepted.

**What happens when the source blocks a request?** Three bounded attempts run before the terminal decision. Zero delivered records fails loud and bills nothing; an interruption after delivery is labeled `PARTIAL`.

**Why can description be null?** Description retrieval is optional, and some public detail fragments are missing, removed, or blocked. `description_status` records the reason.

**Does a zero-row run mean the actor succeeded?** Only a usable public response with no matching cards is `GENUINE_EMPTY`. Login pages, challenges, 403/429/5xx responses, and timeouts are block-class outcomes.

### Compliance

Public logged-out job postings only; transparent `NexGenWatchBot/1.0` user agent; no authentication, profiles, people data, CAPTCHA solving, browser spoofing, paywall circumvention, or anti-bot defeat. Comply on objection.

# Actor input Schema

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

Words that must describe the public job postings you want, such as data engineer or product manager.

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

Optional place name, such as United States, London, or Remote.

## `jobType` (type: `string`):

Optional public-posting employment-type filter.

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

Limit results to recently published public postings.

## `maxResults` (type: `integer`):

Maximum records delivered and billed. The hard per-run ceiling is 500.

## `fetchDescriptions` (type: `boolean`):

Request each public posting's detail fragment and include its description when available. Blocked detail requests remain null and make the run PARTIAL.

## `watchMode` (type: `boolean`):

Seed a saved baseline on the first run, then deliver only new, changed, or repeatedly missing postings. The seed run emits zero records.

## `watchLabel` (type: `string`):

Optional label that keeps otherwise identical saved queries in separate baselines.

## Actor input object example

```json
{
  "keywords": "data engineer",
  "location": "United States",
  "jobType": "any",
  "datePosted": "past-week",
  "maxResults": 5,
  "fetchDescriptions": false,
  "watchMode": false,
  "watchLabel": ""
}
```

# Actor output Schema

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

The delivered public job-posting records.

# 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",
    "location": "United States",
    "jobType": "any",
    "datePosted": "past-week",
    "maxResults": 5,
    "fetchDescriptions": false,
    "watchMode": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexgenwatch/linkedin-job-postings-api").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",
    "location": "United States",
    "jobType": "any",
    "datePosted": "past-week",
    "maxResults": 5,
    "fetchDescriptions": False,
    "watchMode": False,
}

# Run the Actor and wait for it to finish
run = client.actor("nexgenwatch/linkedin-job-postings-api").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",
  "location": "United States",
  "jobType": "any",
  "datePosted": "past-week",
  "maxResults": 5,
  "fetchDescriptions": false,
  "watchMode": false
}' |
apify call nexgenwatch/linkedin-job-postings-api --silent --output-dataset

```

## MCP server setup

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

```

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/MZupbnzcpiIKhkBeh/builds/alZY3zEsKFBYbpW4v/openapi.json
