# LinkedIn Company Scraper: Hiring Signals & Posts (No Cookies) (`meskaoui.azeddine/linkedin-company-intelligence`) Actor

LinkedIn company scraper that goes beyond the page: firmographics, open jobs and hiring signals (functions, seniority, countries, tech stack from job ads), posting activity, momentum score, change monitoring and a white-label PDF report. No cookies, no account. From $3 per 1,000 companies.

- **URL**: https://apify.com/meskaoui.azeddine/linkedin-company-intelligence.md
- **Developed by:** [Azeddine MESKAOUI](https://apify.com/meskaoui.azeddine) (community)
- **Categories:** Lead generation, Jobs, Social media
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 Company Scraper: Hiring Signals & Posts (No Cookies)

Most LinkedIn company scrapers stop at the company page. This one reads the page **and** what the company is doing right now, then gives you one row per company that answers three questions: who are they, are they hiring, are they active.

No LinkedIn account, no cookies, no browser extension. Only pages that LinkedIn shows to anyone.

### What you get for each company

**1. Company profile**
Name, tagline, description, website and domain, industry, size range, employees on LinkedIn, followers, company type, founding year, headquarters, postal address, all office locations, specialties, logo, similar companies.

**2. Hiring signals**

- Number of open jobs, and how many were posted in the last 7 days
- Open jobs per 100 employees (hiring intensity)
- Split by function (Sales, Engineering, Data & AI, Marketing, Finance…), by seniority and by country
- Technologies named in the job ads (Salesforce, HubSpot, SAP, Python, AWS, Snowflake… about 150 recognised)
- Salaries when the ad shows them
- The list of jobs: title, location, date, link

**3. Content activity**
Date of the last post, posts per week, average reactions and comments, engagement per 1,000 followers, formats used, the best recent post, and the list of recent posts.

**4. Momentum score and talking points**
A score from 0 to 100 (`quiet`, `steady`, `growing`, `surging`) and up to five plain sentences you can paste into an outreach message or a briefing:

> Qonto has 82 open roles, 43 of them posted in the last 7 days.
> Hiring is concentrated in Engineering (27% of the listed roles).
> Its job ads mention Swift, GitHub Actions, LLM.

**5. Change monitoring (optional)**
Schedule the Actor and it tells you what moved since the previous run: new jobs, new posts, change in open jobs, employees and followers, edited profile fields. You can ask for the changed companies only.

**6. White-label report (optional)**
A PDF and an HTML briefing per company, with your name and colour. Made for agencies, consultants and sales teams who hand the result to someone else.

### What people use it for

- **Account-based sales.** Rank a target list by momentum, open the conversation with a fact ("you are hiring 12 sales reps in Germany").
- **Sell to the tools they use.** Filter on the technologies found in job ads: companies hiring Salesforce admins, companies mentioning Odoo or SAP.
- **Recruiting agencies.** Find the companies that opened the most roles this week in a function.
- **Competitor watch.** Follow headcount, hiring and posting cadence of competitors, week after week.
- **CRM enrichment.** Turn a column of websites into industry, size, headquarters and LinkedIn URL.
- **Investors and analysts.** Hiring intensity is an early growth signal.

### Input

```json
{
    "companies": ["https://www.linkedin.com/company/odoo", "doctolib.fr", "Qonto"],
    "includeHiringSignals": true,
    "maxJobsPerCompany": 50,
    "jobAdsRead": 10,
    "generateReport": false,
    "monitorChanges": false
}
```

Three kinds of entries work:

| You give | How the company is found | `matchConfidence` |
|---|---|---|
| A LinkedIn company URL | Read directly | `exact` |
| A website (`doctolib.fr`) | The Actor opens the site and follows its own link to LinkedIn. If the site has no such link, the domain name is tried as a handle and kept only when the page points back to it | `verified` when the LinkedIn page points back to the same domain, `linked` or `likely` otherwise |
| A company name (`Qonto`) | Tried as a LinkedIn handle | `guess`: check the `website` column |

For a list of names, prefer websites: the match is safer.

### Output

One row per company. Real output, shortened:

```json
{
    "input": "doctolib.fr",
    "status": "ok",
    "matchedBy": "website-link",
    "matchConfidence": "linked",
    "linkedinUrl": "https://www.linkedin.com/company/doctolib",
    "companyId": "4999584",
    "name": "Doctolib",
    "website": "https://careers.doctolib.com/",
    "industry": "Software Development",
    "companySize": "1,001-5,000 employees",
    "employeesOnLinkedin": 3711,
    "followers": 338698,
    "organizationType": "Privately Held",
    "headquarters": "Levallois-Perret, Île-de-France",
    "countryCode": "FR",
    "specialties": ["Santé", "Internet", "Innovation", "e-health", "telehealth"],
    "similarCompanies": [{ "name": "Qonto", "linkedinUrl": "https://www.linkedin.com/company/qonto" }],
    "openJobs": 172,
    "newJobs7d": 89,
    "topHiringFunction": "Customer Success & Support",
    "technologies": ["Salesforce", "Jira", "Asana"],
    "momentumScore": 83,
    "momentumLabel": "surging",
    "talkingPoints": [
        "Doctolib has 172 open roles, 89 of them posted in the last 7 days.",
        "Hiring is concentrated in Customer Success & Support (22% of the listed roles).",
        "Its job ads mention Salesforce, Jira, Asana.",
        "4 leadership roles (director level and above) are open."
    ],
    "hiring": {
        "openJobs": 172,
        "newJobs7d": 89,
        "newJobsShare7d": 52,
        "openJobsPer100Employees": 4.63,
        "byFunction": [{ "name": "Customer Success & Support", "count": 13, "share": 22 }, { "name": "Data & AI", "count": 13, "share": 22 }],
        "bySeniority": [{ "name": "Senior", "count": 21, "share": 35 }],
        "byArea": [{ "name": "Germany", "count": 36, "share": 60 }, { "name": "France", "count": 24, "share": 40 }],
        "technologies": [{ "name": "Salesforce", "category": "crm", "jobs": 4 }],
        "jobs": [{ "id": "…", "title": "Engineering Manager - Site Reliability & Observability", "location": "Berlin, Berlin, Germany", "postedAt": "2026-10-09", "function": "Engineering", "seniority": "Manager", "url": "…" }]
    },
    "content": {
        "postsAnalyzed": 3,
        "lastPostAt": "2026-10-07T08:02:59.153Z",
        "daysSinceLastPost": 2,
        "postsPerWeek": 1.8,
        "avgReactions": 96.7,
        "avgComments": 13.3,
        "engagementPer1kFollowers": 0.32,
        "topPost": { "url": "…", "reactions": 146, "comments": 13, "text": "…" }
    },
    "scrapedAt": "2026-10-09T21:14:02.000Z"
}
```

The dataset has three table views: **Companies**, **Company profiles** and **Signals and talking points**.

### How the figures are computed

- **Open jobs** is LinkedIn's own count for the company (and the entities that post jobs for it), worldwide unless you set a location.
- **Breakdowns** by function, seniority and area are computed on the jobs listed (`maxJobsPerCompany`, most recent first). Function and seniority are read from the job title, in English, French, German and Spanish.
- **Technologies** come from the job ads read in full (`jobAdsRead`). Raise it for a fuller list.
- **Content activity** covers the posts LinkedIn shows on the public page, usually the last ten.
- **Momentum** = hiring (60%: open jobs relative to headcount, share of jobs opened in the last 7 days) + content (40%: recency, cadence, engagement). 65 and above is `surging`, 40 `growing`, 15 `steady`, below `quiet`. If you turn one part off, the score uses the other.

### Monitoring

Turn on **Monitor changes between runs** and schedule the Actor. Each row gets a `changes` object:

```json
{
    "firstSeen": false,
    "previousCheckAt": "2026-10-02T07:00:11.000Z",
    "employeesDelta": 14,
    "followersDelta": 320,
    "openJobsDelta": 9,
    "newJobs": [{ "title": "Account Executive DACH", "location": "Berlin, Germany", "url": "…" }],
    "newPosts": [{ "url": "…", "text": "…" }],
    "fieldsChanged": [{ "field": "companySize", "from": "201-500 employees", "to": "501-1,000 employees" }]
}
```

`hasChanges` is true when there is a new job, a new post, a change in open jobs or employees, or an edited field. Use **Watchlist name** to keep separate lists.

### Pricing

You pay per result, with three events:

- **Company profile**: one per company delivered. Includes the profile, the content activity, the momentum score and the talking points.
- **Hiring signals**: one per company whose jobs were read. Turn the option off if you only need profiles.
- **Company report**: one per PDF/HTML report, only when reports are turned on.

Companies that are not found, not public or blocked cost nothing. With monitoring and "only changed companies", an unchanged company is still read and is charged as a company profile, without hiring-signals event.

A run of 100 companies with hiring signals takes about six minutes.

### Limits you should know

- Only public company pages. A few small pages are visible to signed-in members only: they come back as `not-public` and are not charged.
- No personal profiles, no employee lists, no emails of people. This Actor is about companies.
- LinkedIn does not show funding rounds on public pages, so they are not in the output.
- Companies that could not be read (`not-found`, `not-public`, `blocked`) are listed in the output with the reason and are never charged.

### Integrations

The output is flat enough for Google Sheets, Airtable, HubSpot, n8n, Make and Zapier: use `name`, `domain`, `openJobs`, `newJobs7d`, `momentumScore`, `talkingPoints`. Call it from the Apify API or as a tool from an AI agent through the Apify MCP server.

# Actor input Schema

## `companies` (type: `array`):

One company per line. Accepted: a LinkedIn company URL (<b>https://www.linkedin.com/company/odoo</b>), a website (<b>odoo.com</b>, the Actor follows the LinkedIn link found on the site), or a company name (<b>Odoo</b>, matched by handle and flagged as a guess).

## `includeHiringSignals` (type: `boolean`):

Reads the open jobs of the company: how many, how many in the last 7 days, split by function, seniority and country, and the technologies named in the job ads. Charged as a separate event.

## `includeContentActivity` (type: `boolean`):

Analyses the latest posts shown on the company page: last post date, posts per week, average reactions and comments, best post. Included in the company profile, no extra charge.

## `maxJobsPerCompany` (type: `integer`):

How many open jobs to list, most recent first. The total number of open jobs is always reported, whatever this limit. LinkedIn shows at most 1,000.

## `jobAdsRead` (type: `integer`):

How many of the most recent job ads are opened to read seniority, contract type, salary and the technologies mentioned. More ads give a fuller technology list and take longer.

## `jobsLocation` (type: `string`):

Leave empty for jobs worldwide. Give a country or a city (<b>France</b>, <b>Berlin</b>) to count only the jobs there.

## `includeJobList` (type: `boolean`):

Turn off to keep only the totals and breakdowns.

## `includePostList` (type: `boolean`):

Turn off to keep only the activity figures and the best post.

## `monitorChanges` (type: `boolean`):

Remembers each company and reports what moved since the previous run: new jobs, new posts, change in open jobs, employees and followers, edited profile fields. Schedule the Actor daily or weekly to get alerts.

## `onlyChangedCompanies` (type: `boolean`):

With monitoring on, companies with no new job, no new post and no profile change are left out of the output. They are still read, so they are still charged.

## `monitorName` (type: `string`):

Use different names to keep separate watchlists (for example one per client). Runs with the same name compare against each other.

## `generateReport` (type: `boolean`):

A two to three page briefing of each company with your name and colour on it, ready to send to a client or to a sales team. Charged per report.

## `reportBrandName` (type: `string`):

Shown at the top right of every report. Leave empty for an unbranded report.

## `reportBrandColor` (type: `string`):

A hex colour such as <b>#0a66c2</b>.

## `maxConcurrency` (type: `integer`):

Lower it if many companies come back as blocked.

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

LinkedIn refuses an address after a few dozen pages, so a proxy is required for more than a handful of companies. Blocked companies are reported as such and are not charged.

## Actor input object example

```json
{
  "companies": [
    "https://www.linkedin.com/company/odoo",
    "mistral.ai",
    "Qonto"
  ],
  "includeHiringSignals": true,
  "includeContentActivity": true,
  "maxJobsPerCompany": 50,
  "jobAdsRead": 10,
  "includeJobList": true,
  "includePostList": true,
  "monitorChanges": false,
  "onlyChangedCompanies": false,
  "monitorName": "default",
  "generateReport": false,
  "reportBrandColor": "#0a66c2",
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `companies` (type: `string`):

Profile, hiring signals, content activity, momentum and talking points of every company.

## `reports` (type: `string`):

PDF and HTML report of each company, when reports are turned on.

## `runSummary` (type: `string`):

How many companies were delivered, not found or blocked, and how many requests the run made.

# 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 = {
    "companies": [
        "https://www.linkedin.com/company/odoo",
        "mistral.ai",
        "Qonto"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("meskaoui.azeddine/linkedin-company-intelligence").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 = {
    "companies": [
        "https://www.linkedin.com/company/odoo",
        "mistral.ai",
        "Qonto",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("meskaoui.azeddine/linkedin-company-intelligence").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 '{
  "companies": [
    "https://www.linkedin.com/company/odoo",
    "mistral.ai",
    "Qonto"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call meskaoui.azeddine/linkedin-company-intelligence --silent --output-dataset

```

## MCP server setup

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

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/bjuCCOs1hiO57Qhsk/builds/ZhFYYUmEiRyE4lT3e/openapi.json
