Skip to main content
Thirdwatchthirdwatch
Business & local data

Map a Company's Public LinkedIn Team Without Login

Turn company names or LinkedIn company URLs into structured public employee records for account research, recruiting, and team mapping.

Apr 28, 2026 · 4 min read · 769 words
See the scraper →

Most "org chart" requests are really one of three jobs:

  • find people in a function at a target company;
  • understand which public profiles mention relevant roles;
  • create a shortlist for deeper research.

None of those requires pretending a public search sample is a complete reporting hierarchy.

The LinkedIn Company Employees Scraper accepts company names or LinkedIn company URLs and returns structured public profile rows without cookies or a LinkedIn login.

Run the ready-made Task: Map a company's public LinkedIn team.

Run a Basic company search

import os
import requests

actor = "thirdwatch~linkedin-company-employees-scraper"
token = os.environ["APIFY_TOKEN"]

response = requests.post(
    f"https://api.apify.com/v2/acts/{actor}/run-sync-get-dataset-items",
    params={"token": token},
    json={
        "queries": [
            "https://www.linkedin.com/company/stripe/",
            "https://www.linkedin.com/company/adyen/",
            "Ramp",
        ],
        "mode": "basic",
        "maxResults": 100,
    },
    timeout=1800,
)
response.raise_for_status()
people = response.json()

Company URLs are more precise. Names are convenient when you do not have the URL, but inspect sourceCompany, sourceQuery, and the returned headline for false positives.

Basic output

{
  "fullName": "Jane Doe",
  "firstName": "Jane",
  "lastName": "Doe",
  "headline": "VP Engineering at Example",
  "url": "https://www.linkedin.com/in/jane-doe/",
  "publicIdentifier": "jane-doe",
  "currentTitle": "VP Engineering",
  "currentCompany": "",
  "experience": [
    {"position": "VP Engineering"}
  ],
  "sourceCompany": "example",
  "sourceQuery": "https://www.linkedin.com/company/example/",
  "resultMode": "basic",
  "scrapedAt": "2026-07-20T13:00:00Z"
}

The current title is normalized from the public search result. Basic discovery does not assert an employer, so currentCompany can be blank. sourceCompany is the company you searched, not an independent verification of the person's employment.

Refine by title or location

{
  "queries": ["https://www.linkedin.com/company/cloudflare/"],
  "mode": "basic",
  "jobTitle": "Security Engineer",
  "location": "London",
  "maxResults": 100
}

These values become search phrases. They improve focus but do not behave like strict SQL filters. If exact inclusion rules matter, filter currentTitle, headline, and Full-mode location after collection.

import re

security = re.compile(r"\b(security|trust|abuse|risk)\b", re.I)
london_profiles = [
    person for person in people
    if security.search(
        " ".join(filter(None, [person.get("currentTitle"), person.get("headline")]))
    )
    and "london" in (person.get("location") or "").lower()
]

Basic rows often have no location. Use Full mode if location is required for qualification.

Use Full mode on a shortlist

Full mode attempts to read public profile metadata for each discovered person. Depending on what LinkedIn exposes anonymously, a row may include:

  • public location and profile summary;
  • work history with company, role, dates, and duration;
  • education;
  • listed skills;
  • certifications and languages;
  • profile photo and public follower count.
{
  "queries": ["https://www.linkedin.com/company/anthropic/"],
  "mode": "full",
  "jobTitle": "Research Engineer",
  "maxResults": 20
}

Restricted profiles can block enrichment. In that case the Actor returns a Basic row with resultMode: "basic" and charges the lower Basic event. It does not fill missing Full fields with guesses.

Group the public sample by role

from collections import Counter

def role_family(person):
    title = (person.get("currentTitle") or person.get("headline") or "").lower()
    if any(term in title for term in ("engineer", "developer", "sre", "architect")):
        return "engineering"
    if any(term in title for term in ("sales", "account executive", "revops")):
        return "sales"
    if any(term in title for term in ("marketing", "growth", "content")):
        return "marketing"
    return "other"

visible_role_mix = Counter(role_family(person) for person in people)
print(visible_role_mix)

Call this a visible role mix. Do not call it the company's actual departmental headcount, because search visibility varies by profile and query.

Deduplicate across queries

The same person can appear in a broad company search and a title-specific search. Use the LinkedIn URL as the natural key.

by_url = {person["url"]: person for person in people if person.get("url")}
people = list(by_url.values())

Monitor newly visible profiles

Set monitorMode to new-employees for a scheduled watch. The first run returns a baseline. Later runs return only unseen profiles confirmed in two consecutive complete snapshots.

The monitor intentionally ignores disappearances. A missing public result does not prove a departure. Read the monitoring guide before using the feed as a hiring signal.

Pricing

Event FREE GOLD
Basic profile $0.003 $0.0015
Full public profile $0.008 $0.005
Completed company search $0.020 $0.015

One company search returning 100 Basic rows costs about $0.32 on FREE. Full-mode rows are charged at the Full rate only when enrichment succeeds.

Practical limits

  • Public search is not exhaustive.
  • Common company names can be ambiguous.
  • Title and location refinements can return adjacent matches.
  • Private or login-walled profiles have fewer fields.
  • The Actor does not return private emails, direct dials, reporting lines, exact headcount, or verified departures.
  • Profile data is personal data. Use it for a lawful purpose, minimize what you retain, and honor applicable privacy and outreach rules.

Frequently asked questions

What does the Actor return in Basic mode?

Basic mode returns public profile name, headline, LinkedIn URL, normalized name and current-role fields, source company, source query, and observation time.

Is the result a complete org chart?

No. Public search returns a ranked sample. The dataset is useful for discovering people and role clusters, not for asserting complete reporting lines or exact headcount.

When should I use Full mode?

Use Full mode for a reviewed shortlist when public work history, education, skills, certifications, languages, or location will change your decision.

Do I need LinkedIn cookies?

No. The Actor works from anonymously visible public data and does not require a LinkedIn account.

Related

Try it yourself

100 free credits, no credit card.

About 30 real searches. Add the MCP to Claude or Cursor in two minutes.