# LinkedIn Jobs Intelligence & Hiring Signals (`scraping_solutions/linkedin-jobs-intelligence-hiring-signals`) Actor

Find fresh LinkedIn jobs, filter applicant competition, enrich hiring companies, remove duplicates, and rank company-level hiring signals. No login or cookies.

- **URL**: https://apify.com/scraping\_solutions/linkedin-jobs-intelligence-hiring-signals.md
- **Developed by:** [Scraping Solutions](https://apify.com/scraping_solutions) (community)
- **Categories:**
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.65 / 1,000 linkedin 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?

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 Intelligence & Hiring Signals

Find current LinkedIn jobs, remove irrelevant vacancies, and turn public hiring activity into structured intelligence for recruiting, job boards, sales, ABM, and market research.

The Actor combines multiple job queries with multiple locations, applies server-side and local filters, removes duplicates, streams clean records, and can optionally enrich every job with application metrics and company intelligence. No LinkedIn login, cookies, or account session is required.

### Why use this Actor?

A basic job scraper answers: **Which jobs are available?** This Actor also helps answer:

- Which companies are actively building teams in a market?
- Which roles and skills are they investing in?
- Which openings have lower visible applicant competition?
- Which companies fit a target employee range?
- Which hiring signals are new since the previous run?
- Which companies have several simultaneous openings?

Every exported job receives an explainable `hiringSignalScore` and `hiringSignalReasons`. The run also creates `COMPANY_SIGNALS`, a company-level summary ranked by the number and strength of discovered openings.

### Two cost-controlled modes

#### 1. Job search

Returns job ID, title, company, LinkedIn and application URLs, location, workplace type, publication date, description, skills, benefits, salary when available, Easy Apply, promotion status, and visible applicant count.

#### 2. Job and company enrichment

Adds experience level, functions, industries, expiration date, job state, views, applications, company employee count, company description, specialties, headquarters, and logo.

Enable enrichment only when those fields are important. It uses one `job-enrichment` event for every job successfully checked. Failed detail requests are not charged as enrichment.

### Quick start

```json
{
  "keywords": ["data engineer", "analytics engineer"],
  "locations": ["United States", "Canada"],
  "resultsPerSearch": 100,
  "searchCoverage": "balanced",
  "datePosted": "week",
  "sortBy": "recent",
  "workplaceType": "remote",
  "maximumApplicants": 50,
  "fetchFullDetails": false
}
```

Two keywords and two locations create four search combinations. Duplicate LinkedIn job IDs are exported only once.

### Advanced hiring-intelligence example

```json
{
  "keywords": ["ecommerce analytics", "marketing automation"],
  "locations": ["United States"],
  "resultsPerSearch": 100,
  "searchCoverage": "balanced",
  "datePosted": "month",
  "experienceLevel": "mid_senior",
  "includeTitleKeywords": ["analytics", "automation"],
  "excludeTitleKeywords": ["intern", "commission only"],
  "excludeCompanies": ["Example Staffing"],
  "fetchFullDetails": true,
  "minimumCompanyEmployees": 200,
  "maximumCompanyEmployees": 5000,
  "excludeRecruitingAgencies": true
}
```

Company-size and agency filters require enrichment because those decisions depend on the detailed company profile. Successfully checked jobs use the enrichment event even if a requested company filter later excludes them.

### Input

| Input | What it controls |
|---|---|
| `keywords` | Job titles, skills, technologies, or company terms. |
| `locations` | Countries, cities, regions, or LinkedIn geo IDs. |
| `resultsPerSearch` | Maximum accepted jobs for every keyword-location combination. |
| `searchCoverage` | Extra pages checked when duplicates or local filters reduce results. |
| `datePosted` | Any time, past day, week, or month. |
| `sortBy` | Most recent or most relevant. |
| `workplaceType` | On-site, remote, or hybrid. |
| `experienceLevel` | Internship through executive. |
| `jobType` | Full-time, part-time, contract, internship, or other. |
| `easyApplyOnly` | Request only Easy Apply jobs. |
| `under10ApplicantsOnly` | Request openings marked as having fewer than ten applicants. |
| `includeTitleKeywords` | Keep titles containing at least one term. |
| `excludeTitleKeywords` | Remove titles containing any term. |
| `includeCompanies` | Keep only matching company names. |
| `excludeCompanies` | Remove matching company names. |
| `excludeLocations` | Remove displayed locations containing a listed term. |
| `minimumApplicants` / `maximumApplicants` | Filter by visible applicant count; unknown counts are excluded. |
| `skipJobIds` | Skip IDs already processed in an earlier run. |
| `fetchFullDetails` | Add job and company intelligence. |
| `minimumCompanyEmployees` / `maximumCompanyEmployees` | Filter enriched companies by employee count. |
| `excludeRecruitingAgencies` | Heuristically exclude likely staffing and recruitment firms. |

### Search coverage

- `efficient`: checks one additional page and minimizes provider calls.
- `balanced`: checks up to three additional pages and is recommended for most runs.
- `thorough`: checks up to six additional pages when strict local filters matter more than speed.

Coverage is a ceiling, not a guarantee. Pagination stops early when the requested result limit is reached, the provider returns no jobs, or a repeated page is detected.

### Output example

```json
{
  "jobId": "4446415722",
  "title": "Senior Data Engineer",
  "jobUrl": "https://www.linkedin.com/jobs/view/4446415722",
  "applyUrl": "https://company.example/jobs/4446415722",
  "companyName": "Example Analytics",
  "companyId": "798671",
  "companyUrl": "https://www.linkedin.com/company/example-analytics",
  "location": "Latin America",
  "workplaceType": "Remote",
  "postedAt": "2026-08-30 18:58:07",
  "description": "Public job description...",
  "applicantCount": 14,
  "viewCount": 231,
  "experienceLevel": "Mid-Senior level",
  "industries": ["IT Services and IT Consulting"],
  "jobFunctions": ["Engineering"],
  "companyStaffCount": 850,
  "companySpecialties": ["Analytics", "Cloud Computing"],
  "companyHeadquarters": {"city": "Austin", "country": "US"},
  "hiringSignalScore": 90,
  "hiringSignalReasons": [
    "Active public job posting",
    "Remote hiring",
    "Company size available",
    "Low visible applicant competition"
  ],
  "detailEnriched": true,
  "sourceKeywords": "data engineer",
  "requestedLocation": "United States"
}
```

LinkedIn does not expose every field for every vacancy. Missing salary, applicant, view, or company fields are returned as `null` or empty arrays instead of invented values.

### Additional run outputs

- `OUTPUT`: totals, provider requests, skipped duplicates, filtered records, enrichment results, and stop reason indicators.
- `COMPANY_SIGNALS`: up to 250 companies ranked by job count, with titles, locations, remote-job count, and average hiring-signal score.
- `RUN_PLAN`: search combinations, coverage, maximum planned calls, and the internal provider-cost estimate used as a safeguard.
- `RUN_PROGRESS`: the most recently completed search page or enrichment batch.

### Incremental monitoring

Use `skipJobIds` to pass IDs stored by your workflow from the previous run. Those jobs are discarded before output, which is safer than sharing one persistent global state between unrelated Actor users.

A typical scheduled workflow is:

1. Run the Actor daily or weekly.
2. Store the exported `jobId` values in your database, Sheet, or automation tool.
3. Send those values as `skipJobIds` on the next run.
4. Process only newly discovered openings.

### Pricing

- Every valid dataset row uses Apify's `apify-default-dataset-item` event.
- Every successfully retrieved full-detail record uses `job-enrichment` when enrichment is enabled.
- Failed searches, failed detail calls, retries, duplicates, and invalid rows are not dataset results.
- Platform usage is intended to be included in the event prices.

Suggested launch prices:

| Event | Free | Starter | Scale | Business |
|---|---:|---:|---:|---:|
| Job result | $1.20 / 1,000 | $1.10 / 1,000 | $1.00 / 1,000 | $0.90 / 1,000 |
| Job enrichment | $5.00 / 1,000 | $4.80 / 1,000 | $4.50 / 1,000 | $4.20 / 1,000 |

A search-only run returning 1,000 jobs costs approximately `$0.90-$1.20`. Enriching all 1,000 jobs adds approximately `$4.20-$5.00`. The exact total can be lower when fewer results or details are successfully produced.

### Reliability and safeguards

- Results stream to the default dataset page by page or enrichment batch by enrichment batch.
- Provider errors `429`, temporary server failures, empty responses, and invalid JSON retry after 3, 9, and 27 seconds.
- A repeated-page signature prevents infinite pagination loops.
- Jobs are deduplicated across overlapping searches by LinkedIn job ID or canonical URL.
- The Actor validates pricing and available result capacity before paid provider work.
- Enrichment batches reserve room for both the enrichment event and exported result.
- Provider requests have a hard plan-based ceiling.
- Free users receive a protected sample of up to 50 jobs.

### Support and responsible use

This Actor processes publicly available job and company information. It does not require LinkedIn credentials or cookies. Use the data in accordance with applicable laws, platform terms, employment rules, and your organization's data-retention policies.

For support, share the Apify run ID and a sanitized input. Never include private API keys, cookies, or personal access tokens.

# Actor input Schema

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

Add one query per line. Each query is combined with every location below.

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

Country, city, region, or LinkedIn geo ID. Leave empty to search everywhere.

## `resultsPerSearch` (type: `integer`):

The limit applies to each keyword-location combination. Duplicate job IDs are not exported twice.

## `searchCoverage` (type: `string`):

Controls how many extra pages are checked when duplicates or local filters reduce the output. Balanced is recommended.

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

Limit results to recently published jobs.

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

Choose whether the provider prioritizes freshness or relevance.

## `workplaceType` (type: `string`):

Limit results to on-site, remote, or hybrid roles.

## `experienceLevel` (type: `string`):

Limit results to one public LinkedIn experience level.

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

Limit results to one employment arrangement.

## `easyApplyOnly` (type: `boolean`):

Return only jobs with LinkedIn Easy Apply.

## `under10ApplicantsOnly` (type: `boolean`):

Prioritize lower-competition job opportunities when LinkedIn exposes this filter.

## `includeTitleKeywords` (type: `array`):

Optional local filter. Keep jobs whose title contains at least one term.

## `excludeTitleKeywords` (type: `array`):

Remove jobs whose title contains any listed term.

## `includeCompanies` (type: `array`):

Optional company allowlist. Partial, case-insensitive names are accepted.

## `excludeCompanies` (type: `array`):

Remove jobs from matching company names.

## `excludeLocations` (type: `array`):

Remove results whose displayed location contains any listed term.

## `minimumApplicants` (type: `integer`):

Set 0 to disable. Jobs without a visible applicant count are excluded when this filter is active.

## `maximumApplicants` (type: `integer`):

Set 0 to disable. Useful for finding lower-competition openings.

## `skipJobIds` (type: `array`):

Optional incremental-run list. Matching LinkedIn job IDs are skipped without being exported again.

## `fetchFullDetails` (type: `boolean`):

Fetch job functions, industries, expiry, views, applications, company size, specialties, description, logo, and headquarters. Charged once per successfully checked job using the job-enrichment event.

## `minimumCompanyEmployees` (type: `integer`):

Set 0 to disable. Requires enrichment; successfully checked jobs are charged even when this filter excludes them.

## `maximumCompanyEmployees` (type: `integer`):

Set 0 to disable. Requires enrichment; jobs with unavailable company size are excluded.

## `excludeRecruitingAgencies` (type: `boolean`):

Uses enriched company descriptions and specialties to remove likely staffing and recruitment firms. This is a heuristic, not a guarantee.

## Actor input object example

```json
{
  "keywords": [
    "software engineer",
    "data engineer"
  ],
  "locations": [
    "United States",
    "Ecuador"
  ],
  "resultsPerSearch": 100,
  "searchCoverage": "balanced",
  "datePosted": "week",
  "sortBy": "recent",
  "workplaceType": "",
  "experienceLevel": "",
  "jobType": "",
  "easyApplyOnly": false,
  "under10ApplicantsOnly": false,
  "includeTitleKeywords": [],
  "excludeTitleKeywords": [],
  "includeCompanies": [],
  "excludeCompanies": [],
  "excludeLocations": [],
  "minimumApplicants": 0,
  "maximumApplicants": 0,
  "skipJobIds": [],
  "fetchFullDetails": false,
  "minimumCompanyEmployees": 0,
  "maximumCompanyEmployees": 0,
  "excludeRecruitingAgencies": false
}
```

# Actor output Schema

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

Filtered and deduplicated LinkedIn jobs stored in the default dataset.

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

Filtered and deduplicated LinkedIn jobs stored in the default dataset.

## `summary` (type: `string`):

Counts, filters, enrichment, billing, and provider-request diagnostics.

## `companySignals` (type: `string`):

Company-level aggregation of the jobs exported by this run.

## `runPlan` (type: `string`):

Preflight search combinations, limits, coverage, and maximum provider requests.

# 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": [
        "software engineer",
        "data engineer"
    ],
    "locations": [
        "United States",
        "Ecuador"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraping_solutions/linkedin-jobs-intelligence-hiring-signals").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": [
        "software engineer",
        "data engineer",
    ],
    "locations": [
        "United States",
        "Ecuador",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("scraping_solutions/linkedin-jobs-intelligence-hiring-signals").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": [
    "software engineer",
    "data engineer"
  ],
  "locations": [
    "United States",
    "Ecuador"
  ]
}' |
apify call scraping_solutions/linkedin-jobs-intelligence-hiring-signals --silent --output-dataset

```

## MCP server setup

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

```

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/9KB6XKOrwbSOHAvNj/builds/rbgsrXXJfc9SSMcUB/openapi.json
