# LinkedIn Jobs Scraper — Salary, Applicants & Company Data (`foxlabs/linkedin-jobs-scraper`) Actor

Scrape public LinkedIn jobs by keyword & location — no login. Title, company, location, full description, seniority, employment type, applicant count, PARSED salary, and optional company firmographic enrichment (employees, industry, HQ, domain). For recruiting, market research & sales intent.

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

## Pricing

from $4.00 / 1,000 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

<p align="center"><a href="https://apify.com/foxlabs/linkedin-jobs-scraper"><img src="https://data.foxlabs.com.tr/img/linkedin-jobs-scraper-banner.svg" alt="LinkedIn Jobs Scraper — Salary, Applicants & Company Data" width="100%" /></a></p>

## LinkedIn Jobs Scraper — Salary, Applicants & Company Data

Need **structured LinkedIn job-posting data** — not a brittle HTML dump or a scraper that asks for your account cookies? This Actor searches LinkedIn's **public guest job listings** by keyword and location and returns clean, ready-to-use records: title, company (+ LinkedIn page), location, full description, seniority, employment type, applicant count, and a **parsed salary object** — plus **optional employer firmographics** (employee count, industry, HQ, domain, followers) pulled inline from the company page.

**No login, no cookies, no account risk** — it reads only what a logged-out visitor can see, so you never put a LinkedIn account on the line. Built for recruiting, talent-market research, and **sales-intent** signals (who is hiring, for what, how competitively).

- 💼 **Full job records** — title, company, location, full description, seniority, type, applicant count
- 💰 **Parsed salary** — a real `{ min, max, currency, period }` object, not a raw string
- 🏢 **Optional employer firmographics** — employee count, industry, HQ, domain, followers, founded — inline per job
- 🔓 **No login, no cookies** — public guest data only, so an account is never at risk

### Quick start (API)

Get 100 software-engineer jobs posted in New York this past week, in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/foxlabs~linkedin-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "keywords": "software engineer", "location": "New York", "datePosted": "week", "maxResults": 100 }'
```

Prefer no code? Open the **Input** tab, type your **keywords** and **location**, set your filters, and click **Start** — then download the results.

### What you get

One clean, flat record per job. A default run (details on) returns:

| Field | Type | Description |
|---|---|---|
| `jobId` | string | LinkedIn's numeric job-posting ID |
| `jobUrl` | string | Canonical public job URL (`/jobs/view/{jobId}`) |
| `title` | string | Job title |
| `companyName` | string | Employer name |
| `companyLinkedInUrl` | string | Employer's LinkedIn company-page URL |
| `companySlug` | string | Company slug parsed from that URL (lower-cased) |
| `companyLogo` | string | Company logo image URL |
| `location` | string | Job location as shown on the listing |
| `workplaceType` | string | `Remote` / `Hybrid` / `On-site` — when LinkedIn tags it in the card text |
| `postedDate` | string | ISO date the job was posted |
| `postedTimeAgo` | string | Human relative time, e.g. *"1 week ago"* |
| `benefits` | string | Benefits summary, on the rare listing where LinkedIn attaches one (e.g. *"Medical insurance +3 benefits"*). **Uncommon** — measured on 1 of 152 sampled cards; most perks appear only as prose inside `descriptionText` |
| `listingBadge` | string | LinkedIn's promo badge for the listing — *"Actively Hiring"*, *"Be an early applicant"*. LinkedIn renders it in the same slot as the benefits summary, so it is split out here instead of being mislabelled as a benefit |
| `descriptionText` | string | Full job description, plain text |
| `descriptionHtml` | string | Full job description, original HTML |
| `seniorityLevel` | string | e.g. *Mid-Senior level*, *Entry level* |
| `employmentType` | string | e.g. *Full-time*, *Contract* |
| `jobFunction` | string | e.g. *Engineering and Information Technology* |
| `industries` | string | Industry label(s) for the role |
| `applicantCount` | number | Applicant number LinkedIn shows, parsed. **Read it with the two bound flags below** — LinkedIn states an exact figure on only a minority of jobs |
| `applicantCountIsLowerBound` | boolean | `true` when LinkedIn said *"Over 200 applicants"* — `applicantCount` is a **floor**, the real number is higher |
| `applicantCountIsUpperBound` | boolean | `true` when LinkedIn said *"Be among the first 25 applicants"* — `applicantCount` is a **ceiling**, fewer than that have applied |
| `applicantCountText` | string | Raw applicant text, e.g. *"87 applicants"*, *"Over 200 applicants"* |
| `jobPoster` | object | Best-effort hiring contact `{ name, title, profileUrl }` — usually absent when logged-out |
| `salaryMin` | number | Parsed minimum pay |
| `salaryMax` | number | Parsed maximum pay (omitted when pay is a single figure) |
| `salaryCurrency` | string | Currency code — `USD`, `GBP` or `EUR` |
| `salaryPeriod` | string | `yearly` / `hourly` / `monthly` |
| `salaryFormatted` | string | Compact display, e.g. `$150K–$220K/yr` |
| `salaryRaw` | string | The raw compensation text salary was parsed from |
| `source` | string | Always `"LinkedIn (public)"` |
| `scrapedAt` | string | ISO timestamp of the scrape |

Turn on **Enrich with company firmographics** and each record also carries employer data pulled inline from the company's public LinkedIn page:

| Field | Type | Description |
|---|---|---|
| `companyEmployeeCount` | number | Employee count from the company page |
| `companyFollowers` | number | LinkedIn follower count |
| `companyIndustry` | string | Company industry |
| `companyWebsite` | string | Company website URL |
| `companyDomain` | string | Bare domain of that website |
| `companyHQ` | string | HQ location (city, region, country) |
| `companyFounded` | number | Founding year |

> Fields with no value are **omitted** from the record (not returned as `null`), so every record is compact. Salary fields appear only where LinkedIn actually displays compensation.

#### Sample output

Illustrative record (details + company enrichment on; fields shown fully populated — a real record omits any field LinkedIn doesn't show):

```json
{
  "jobId": "3901234567",
  "jobUrl": "https://www.linkedin.com/jobs/view/3901234567",
  "title": "Senior Software Engineer",
  "companyName": "Datadog",
  "companyLinkedInUrl": "https://www.linkedin.com/company/datadog",
  "companySlug": "datadog",
  "companyLogo": "https://media.licdn.com/dms/image/v2/D4E0BAQ.../company-logo_100_100/0/logo.png",
  "location": "New York, NY",
  "workplaceType": "Hybrid",
  "postedDate": "2026-06-28",
  "postedTimeAgo": "1 week ago",
  "listingBadge": "Actively Hiring",
  "descriptionText": "About the role: We're hiring a Senior Software Engineer to build and scale our observability platform. You'll own services end to end, from design through production...",
  "descriptionHtml": "<p><strong>About the role:</strong> We're hiring a Senior Software Engineer...</p>",
  "seniorityLevel": "Mid-Senior level",
  "employmentType": "Full-time",
  "jobFunction": "Engineering and Information Technology",
  "industries": "Software Development",
  "applicantCount": 200,
  "applicantCountIsLowerBound": true,
  "applicantCountText": "Over 200 applicants",
  "salaryMin": 150000,
  "salaryMax": 220000,
  "salaryCurrency": "USD",
  "salaryPeriod": "yearly",
  "salaryFormatted": "$150K–$220K/yr",
  "salaryRaw": "$150,000.00/yr - $220,000.00/yr",
  "companyEmployeeCount": 7000,
  "companyFollowers": 850000,
  "companyIndustry": "Software Development",
  "companyWebsite": "https://www.datadoghq.com",
  "companyDomain": "datadoghq.com",
  "companyHQ": "New York, NY, US",
  "companyFounded": 2010,
  "source": "LinkedIn (public)",
  "scrapedAt": "2026-07-05T09:12:44.001Z"
}
```

### Input & filters

- **Keywords** — job title, skill or free-text query (e.g. `software engineer`, `account executive`, `react`).
- **Location** — city, region or country (e.g. `New York`, `London`, `Germany`). Leave blank to search worldwide.
- **Workplace type** — LinkedIn's own filter: `remote` / `hybrid` / `on-site`.
- **Date posted** — `24h` / `week` / `month`. Use a short window for fresh hiring signals.
- **Experience level** — `internship`, `entry`, `associate`, `mid-senior`, `director`, `executive`.
- **Employment type** — `full-time`, `part-time`, `contract`, `temporary`, `internship`.
- **Scrape full details** — on by default: opens each job for the full description, seniority, type, applicant count and parsed salary. Turn off for a faster, list-only run.
- **Enrich with company firmographics** — opt-in: appends employer size/industry/HQ/domain/followers to every job.
- **Max results** — 1–1,000 per search (LinkedIn's public cap).

> At least one of **keywords** or **location** is required.

### Example inputs (copy & paste)

```jsonc
// 1) Fresh remote signals: product-manager roles posted this week, remote
{ "keywords": "product manager", "workplaceType": "remote", "datePosted": "week", "maxResults": 200 }

// 2) Enriched hiring feed: London data-engineer jobs + employer firmographics
{ "keywords": "data engineer", "location": "London", "enrichCompany": true, "maxResults": 150 }

// 3) Fast list-only scan (no per-job detail): a wide sales sweep, US
{ "keywords": "sales", "location": "United States", "scrapeDetails": false, "maxResults": 500 }

// 4) Fresh 24h buying signal: RevOps leadership openings, director level
{ "keywords": "Head of RevOps", "datePosted": "24h", "experienceLevel": "director", "maxResults": 100 }

// 5) Contract talent market: freelance React roles, remote
{ "keywords": "react", "jobType": "contract", "workplaceType": "remote", "maxResults": 200 }

// 6) Early-career pipeline: marketing internships, hybrid, Germany
{ "keywords": "marketing", "location": "Germany", "workplaceType": "hybrid", "experienceLevel": "internship", "jobType": "internship", "maxResults": 150 }

// 7) Full-detail + enriched deep pull: executive product roles worldwide
{ "keywords": "VP Product", "experienceLevel": "executive", "scrapeDetails": true, "enrichCompany": true, "maxResults": 300 }
```

### Use cases

- **Recruiting & sourcing.** Pull every open role for a title + location with the full description, seniority and applicant count, so you can see how contested each posting is and where to focus outreach — no manual copy-paste from the LinkedIn UI.
- **Talent-market & salary research.** Where LinkedIn shows pay, you get a structured `salaryMin`/`salaryMax`/`salaryCurrency`/`salaryPeriod` — aggregate it to benchmark compensation by role, seniority and geography instead of eyeballing job ads.
- **Sales-intent & hiring signals.** A company hiring 12 SDRs or a "Head of RevOps" is a buying signal. Filter by keyword + `datePosted: "24h"` to catch fresh openings, and turn on enrichment to qualify each employer by size and industry.
- **Competitor & market monitoring.** Track who a competitor is hiring for, how many roles, and how fast they fill — run the same search on a schedule and diff the results over time.
- **CRM & company enrichment.** Turn on **Enrich with company firmographics** to append employee count, industry, HQ, website and domain to each job — a company-qualified feed, not just a title list.
- **Job boards & aggregators.** Feed a niche board or a Slack/email digest with fresh, structured postings in JSON, CSV or Excel.

### Performance & throughput

The Actor paginates LinkedIn's public guest search 10 cards at a time, **de-duplicates by `jobId`** into a single clean set, then fetches per-job details and (optionally) company firmographics with **bounded concurrency (8 parallel requests)**. Company enrichment is **cached per company**, so scraping 100 jobs from 30 employers does only 30 enrichment fetches — not 100. LinkedIn rate-limits aggressively (HTTP 429 / 999), so each request **retries with backoff** over a residential proxy. Throughput is network- and proxy-bound; a single search is capped at LinkedIn's **~1,000 public results** — narrow with filters (date, workplace, seniority, location) to page deeper into large markets.

### Integrations

**JavaScript** (`apify-client`):

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('foxlabs/linkedin-jobs-scraper').call({
  keywords: 'software engineer', location: 'New York', datePosted: 'week', maxResults: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

**Python** (`apify-client`):

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("foxlabs/linkedin-jobs-scraper").call(run_input={
    "keywords": "software engineer", "location": "New York", "datePosted": "week", "maxResults": 100,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item.get("companyName"), item.get("salaryFormatted"))
```

Also works with **Make / n8n / Zapier** (Apify app → run this Actor, map the input), scheduled runs, webhooks, and the **Apify MCP server** so AI agents can call it as a tool.

### Data quality

- **Nothing is fabricated.** Every field is read from LinkedIn's public pages; when LinkedIn doesn't show a value, the field is simply omitted — never guessed or padded.
- **De-duplicated.** Results are unique by `jobId`; repeated cards across pagination are merged, not double-counted.
- **Salary is scoped, not scraped from prose.** It is parsed only from LinkedIn's compensation element (requiring a currency symbol), so numbers elsewhere in a description can't masquerade as pay. Salary therefore appears only where LinkedIn actually discloses it — mostly **US pay-transparency** roles (an estimated 40–50% of US postings), rarely in the EU where employers don't publish ranges.
- **Enrichment is best-effort.** Company firmographics come from the employer's public page; a field is included only when present there.

### Pricing

**Pay per result** — you're billed for the job records returned, so a tightly-filtered search that matches fewer jobs costs less. Company enrichment reuses a per-company cache, so many jobs at one employer add only one lookup. There's an Apify **free tier** to evaluate the full feature set before you scale, and no third-party API keys to buy.

### FAQ

**Do I need a LinkedIn login or cookies?** No. The Actor reads only LinkedIn's public logged-out job pages — no account, no session cookie, no account risk.

**Can I get the salary for every job?** No — only where LinkedIn itself displays a pay range. That's mostly US pay-transparency roles; elsewhere it's usually absent, and the field is omitted rather than guessed.

**How many jobs can one search return?** Up to ~1,000 — LinkedIn's public search cap. Set `maxResults` up to 1000.

**How do I get more than 1,000 results?** Split the search: run it per **date window**, **workplace type**, **seniority**, **employment type** or **location** and combine the datasets. Each narrower slice pages fresh under the cap.

**What are the company firmographics and how do I get them?** Employee count, followers, industry, website, domain, HQ and founding year — turn on **Enrich with company firmographics**. It adds one request per unique employer (cached).

**Does a field being missing mean the scrape failed?** No. Records are compact by design: any value LinkedIn doesn't show for that job is omitted. Missing salary, benefits or `jobPoster` is normal.

**Why is `applicantCount` not always exact?** Because LinkedIn itself usually isn't. It shows *"Over 200 applicants"* or *"Be among the first 25 applicants"* far more often than a precise figure — in a 25-job sample, 22 rows were one of those two forms and only 3 were exact. Both are kept (they are the strongest signal available), but flagged: filter on `applicantCountIsLowerBound` / `applicantCountIsUpperBound` before averaging the column, or you will be averaging floors and ceilings together.

**What export formats are available?** JSON, CSV, Excel, or via the Apify API and integrations.

**Can I filter by remote/date/seniority/type?** Yes — workplace type, date posted, experience level and employment type all map to LinkedIn's own facets.

**Is the external apply URL or the full hiring team included?** No — those are login-gated fields LinkedIn hides from logged-out visitors, so a cookieless scraper can't see them. A single best-effort `jobPoster` is attempted but is usually absent when logged-out.

**Which proxy should I use?** Residential (the default). LinkedIn rate-limits and blocks un-proxied and datacenter traffic.

### Troubleshooting

- **"Provide at least keywords or location"** → the run needs at least one of the two. Add a keyword or a location and re-run.
- **Fewer results than `maxResults`** → either the search genuinely has fewer matching jobs, or you hit LinkedIn's ~1,000 public cap. Widen the query for more matches, or narrow with filters to page deeper.
- **No salary / no firmographics** → salary appears only where LinkedIn shows it; firmographics require **Enrich with company firmographics** to be turned on.
- **Slow, blocked, or "999" responses** → LinkedIn is rate-limiting. Keep the default **Residential** proxy on; the Actor already retries 429/999 with backoff. Smaller, filtered runs are more reliable than one huge sweep.

### Notes, limits & legal (honest)

- **No official public API.** LinkedIn offers no open jobs API for this; the Actor reads LinkedIn's **public, logged-out** guest job pages. It uses no login and no cookies.
- **Public data only.** Fields LinkedIn hides from logged-out visitors — the external/offsite apply URL and the full recruiter/hiring-team list — are **not** returned. In exchange, you never risk an account.
- **~1,000-result public cap** per search is LinkedIn's, not the Actor's. Use filters to cover larger markets.
- **Personal data.** A best-effort `jobPoster` may include an individual's name and public profile URL. If you process it you are responsible for your own lawful basis (e.g. GDPR); use the data only for legitimate recruiting, research and B2B purposes.
- **Your responsibility.** Respect LinkedIn's Terms of Service and applicable data-protection law in your jurisdiction. You are responsible for how you use the output.
- **Not affiliated** with, endorsed by, or sponsored by LinkedIn Corporation. "LinkedIn" is a trademark of its owner.

### Support

Questions, a field you'd like added, or a custom build? Open the **Issues** tab on this Actor, or email **info@foxlabs.com.tr**. We reply fast.

*If this Actor saves you time, a ⭐ review really helps.*

### Changelog

#### 0.4 — 2026-07-28

- **`benefits` stopped reporting a badge as a perk.** LinkedIn renders its promo badge and its benefits summary through the same element, so the field came back as *"Actively Hiring"* or *"Be an early applicant"* — on a 152-card sample, **116 of the 117 filled rows carried a badge, not a benefit**. The slot is now split: badges go to the new `listingBadge`, and `benefits` only carries a genuine summary (e.g. *"Medical insurance +3 benefits"*, measured 1/152). Verified end to end on a 25-job run: `benefits` 1 row, `listingBadge` 11 rows, zero mislabelled.
- **`applicantCount` no longer passes a bound off as an exact count.** LinkedIn mostly shows *"Over 200 applicants"* (a floor) or *"Be among the first 25 applicants"* (a ceiling); both were emitted as plain integers, so averaging the column mixed exact figures, floors and ceilings. Measured on a 25-job run: **22 of 25 rows were bounds**, and the naive mean was 178.4 against 108.8 over the genuinely exact rows. The number is kept — it is the strongest signal LinkedIn gives — but now travels with `applicantCountIsLowerBound` / `applicantCountIsUpperBound`.

#### 0.3.1 — 2026-07-28

- **Company enrichment is now on in the Console form.** The prefilled input arrives with **Enrich with company firmographics** ticked, so a first run — and the platform's automated health-check — actually exercises the employer data this Actor is named for. Measured on a live run: firmographics resolve for **7 of 12** job rows (**7 of 11** unique employers), where the previous prefill produced **zero**. The `default` is unchanged (**off**), so nothing changes for existing API callers or scheduled tasks.
- **Lighter demo prefill.** The prefilled **Max results** drops from 100 to **10** so the enriched first run finishes in about a minute (measured: 66.8s for 10 results, 76.0s for 12) instead of risking a health-check timeout. The `default` stays **100**.
- **Honest field list.** `companyFounded` was removed from the enrichment description: LinkedIn's public company markup does not publish a founding date and the field measured **0/12** on live runs. The other six firmographic fields are unaffected.

#### 0.3 — 2026-07-16

- **Ultimate beneficial owner (KYB).** Each employer is now resolved to its ultimate beneficial owner — a real person or a cross-border parent — by walking UK holding-company ownership chains (Companies House PSC + GLEIF). See who *really* controls the companies that are hiring (e.g. an employer owned via layers by a US or private-equity parent). Confidence-gated: the owner is attached only when resolved with high confidence, never guessed. New `includeOwnership` option (on by default). No other jobs scraper links postings to real ownership.

#### 0.2 — 2026-07-05

- Reworked docs: API quick-start, complete field table, realistic sample output, JS/Python/Make/MCP integration snippets, expanded FAQ & troubleshooting, honest legal/limits notes.
- Corrected the input schema (removed an apply-URL mention that the Actor does not emit; clarified the enrichment field).

#### 0.1

- Initial release. Keyword/location search with workplace, date, experience and employment-type filters; full description, seniority, job function, industries, applicant count; parsed salary object; opt-in company firmographic enrichment; de-duplicated pagination; cookieless (no login).

***

Part of the **[foXLabs data platform](https://data.foxlabs.com.tr/)** — public-data company, contact, jobs, procurement & AI-search intelligence scrapers. Browse the full suite at **[data.foxlabs.com.tr](https://data.foxlabs.com.tr/)**.

# Actor input Schema

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

Job title, skill or keyword to search — e.g. "software engineer", "account executive", "react".

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

City, region or country — e.g. "New York", "London", "Germany", "European Union". Leave blank to search worldwide.

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

Filter by on-site / remote / hybrid using LinkedIn's own workplace filter.

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

Only jobs posted within this window. Use "Past 24 hours" or "Past week" for fresh hiring signals.

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

Filter by seniority.

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

Filter by full-time / part-time / contract / etc.

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

How many jobs to return (1–1000). LinkedIn's public search caps at ~1000 per query — narrow with filters for large searches.

## `scrapeDetails` (type: `boolean`):

Open each job for its full description, seniority, employment type, job function, industries, applicant count and parsed salary. Turn off for a faster, lighter run (list fields only).

## `enrichCompany` (type: `boolean`):

Add employer firmographics (employee count, industry, HQ, website domain, followers) from the company's public LinkedIn page. One extra request per unique company, cached — repeated employers are not refetched. Resolves for roughly 6 in 10 employers; it also sharpens ownership matching by supplying the employer's domain.

## `includeOwnership` (type: `boolean`):

Resolve each employer to its ULTIMATE beneficial owner — a real person or a cross-border parent company — by walking UK holding-company ownership chains (Companies House PSC + GLEIF). E.g. an employer owned via layers by a US or private-equity parent. Confidence-gated: the owner is only attached when it can be resolved with high confidence (never guessed). Turn on company enrichment to sharpen the match via the employer's domain.

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

Proxy configuration. Residential proxy (the default) is strongly recommended — LinkedIn rate-limits and blocks un-proxied and datacenter traffic.

## Actor input object example

```json
{
  "keywords": "software engineer",
  "location": "United States",
  "workplaceType": "any",
  "datePosted": "any",
  "experienceLevel": "any",
  "jobType": "any",
  "maxResults": 10,
  "scrapeDetails": true,
  "enrichCompany": true,
  "includeOwnership": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (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": "software engineer",
    "location": "United States",
    "maxResults": 10,
    "enrichCompany": true,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("foxlabs/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 = {
    "keywords": "software engineer",
    "location": "United States",
    "maxResults": 10,
    "enrichCompany": True,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("foxlabs/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 '{
  "keywords": "software engineer",
  "location": "United States",
  "maxResults": 10,
  "enrichCompany": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call foxlabs/linkedin-jobs-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/BHQxucS2Cdy5vBsu2/builds/6WzDQzdjZJNgXXW5U/openapi.json
