# LinkedIn Jobs & Company Scraper (`bgfc97/linkedin-jobs-company-scraper`) Actor

Scrape LinkedIn job postings by keyword, location or company. Returns job title, company, location, salary, description, employment type, posted date and apply link. No login or cookies required.

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

## Pricing

$1.60 / 1,000 item scrapeds

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/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 Jobs & Company Scraper

Scrape **LinkedIn job postings** by keyword and location, and **LinkedIn company pages**, using only **public, logged-out ("guest") data** — no LinkedIn account, cookies or login required. Requests are made with browser-grade HTTP fingerprints (`got-scraping`) routed through **Apify Proxy**, with a fresh proxy session generated on every retry, to survive LinkedIn's anti-bot defenses.

### Why it's useful

LinkedIn is one of the richest sources of hiring signal and company data on the web, and one of the hardest to scrape. This actor uses the same technique LinkedIn's own public job-search pages use internally (the `jobs-guest` search API) to pull structured job data reliably without login — and adds best-effort company-page scraping for a quick public snapshot of a company.

### Input

```json
{
  "jobKeywords": ["software engineer", "data analyst"],
  "jobLocation": "United States",
  "companyUrls": ["https://www.linkedin.com/company/google/", "openai"],
  "maxItems": 50
}
```

- `jobKeywords` — search terms; each runs its own paginated job search. Optional if `companyUrls` is set.
- `jobLocation` — one location filter applied to every keyword search. Optional.
- `companyUrls` — LinkedIn company URLs or bare slugs. Optional if `jobKeywords` is set.
- `maxItems` — max job postings per keyword (default 50).
- `proxyConfiguration` — Apify Proxy config; **residential** is strongly recommended.
- `timeoutSecs` — per-request timeout in seconds (default 30).

At least one of `jobKeywords` / `companyUrls` is required.

### Output

**Job posting** (`source: "job"`):

```json
{
  "source": "job",
  "title": "Software Engineer",
  "company": "Example Inc",
  "companyUrl": "https://www.linkedin.com/company/example",
  "location": "San Francisco, CA",
  "postedDate": "2026-09-20",
  "postedDateText": "3 days ago",
  "jobId": "4012345678",
  "jobUrl": "https://www.linkedin.com/jobs/view/software-engineer-at-example-4012345678",
  "keyword": "software engineer",
  "searchLocation": "United States"
}
```

**Company** (`source: "company"`) — best effort; LinkedIn gates most company-page content behind a login wall for guests, so fields may be `null` and a `note` explains when that happened:

```json
{
  "source": "company",
  "input": "google",
  "url": "https://www.linkedin.com/company/google/",
  "name": "Google",
  "industry": "Software Development",
  "size": "10,001+ employees",
  "headquarters": "Mountain View, CA",
  "organizationType": "Public Company",
  "specialties": "search, ads, mobile, android, ...",
  "followers": "42,415,536",
  "about": "...",
  "website": "https://goo.gle/3DLEokh"
}
```

If a request is blocked after 5 retries (each with a fresh residential proxy session), the actor reports it honestly instead of fabricating data:

```json
{ "source": "job", "keyword": "...", "error": "blocked (needs residential proxy): blocked (HTTP 999, 812 bytes)" }
```

### How it works

- **Jobs**: calls the public `linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search` endpoint (the same one LinkedIn's own guest job-search pages use), paginating with `start=0,25,50,…`, and parses the returned job-card HTML.
- **Company**: fetches the public `linkedin.com/company/{slug}/` page and parses whatever is visible in the HTML — JSON-LD `Organization` data, meta tags and known guest-page selectors.
- Every request goes through Apify Proxy with a **new session per attempt** (up to 5 attempts) whenever a response looks blocked (auth wall, captcha, security-check page, or an HTTP 401/403/429/5xx/999).

### Notes

- No login, cookies or LinkedIn account needed — 100% public guest data.
- Honesty over fabrication: if LinkedIn blocks a request even after retries, the actor reports the block rather than inventing data.
- LinkedIn's anti-bot defenses change over time; job search (the guest API) is the most reliable technique, company pages are inherently harder and best-effort.

### ⭐ Enjoying this Actor?

A quick **rating/review** helps others find it. Found a page LinkedIn changed the markup on? Open a ticket on the **Issues** tab.

# Actor input Schema

## `jobKeywords` (type: `array`):

Keywords to search LinkedIn Jobs for (e.g. "software engineer"). Each keyword runs one public guest job search and its results are paginated and scraped. Optional if companyUrls is set — at least one of the two is required.

## `jobLocation` (type: `string`):

Location filter applied to every keyword search (e.g. "United States", "London, England, United Kingdom"). Optional — leave empty to search all locations.

## `companyUrls` (type: `array`):

LinkedIn company page URLs (e.g. https://www.linkedin.com/company/google/) or bare slugs (e.g. google) to scrape individually. Optional if jobKeywords is set — at least one of the two is required. Company pages are gated much harder than job search by LinkedIn, so results here are best-effort and may be incomplete.

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

Maximum number of job postings to scrape per keyword search, paginating 25 results at a time. Company URLs/slugs are always scraped in full regardless of this limit.

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

Apify Proxy settings used for every request, with a fresh proxy session generated for each retry attempt. Residential proxies are strongly recommended — LinkedIn aggressively blocks datacenter IPs with an auth wall or captcha.

## `timeoutSecs` (type: `integer`):

Timeout per HTTP request to LinkedIn, in seconds (5-90).

## Actor input object example

```json
{
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "timeoutSecs": 30
}
```

# Actor output Schema

## `dataset` (type: `string`):

Scrape LinkedIn job postings by keyword/location and LinkedIn company pages — public guest data, no login required. Uses got-scraping with browser-grade fingerprints routed through Apify Proxy (residential, a fresh session per retry attempt) to survive LinkedIn's anti-bot defenses.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("bgfc97/linkedin-jobs-company-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("bgfc97/linkedin-jobs-company-scraper").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 '{}' |
apify call bgfc97/linkedin-jobs-company-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bgfc97/linkedin-jobs-company-scraper"
        }
    }
}
```

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/9jNbgLgxFiNK7N3if/builds/rsctZTVb7tgBW5UWI/openapi.json
