# LinkedIn Profile Search — by Name, Job Title or Company (`endspec/linkedin-instant-profile-search`) Actor

Search LinkedIn profiles by name, job title, or company. Returns matching profiles with full data. Fast, embedded API — no setup, no cookies.

- **URL**: https://apify.com/endspec/linkedin-instant-profile-search.md
- **Developed by:** [EndSpec](https://apify.com/endspec) (community)
- **Categories:** Lead generation, Social media, E-commerce
- **Stats:** 125 total users, 38 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.50 / 1,000 profile returneds

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 Profile Search — Find LinkedIn Profiles by Name, Job Title or Company

**Simple Input-Output Example**

Input:

```json
{
  "query": "Software Engineer Google",
  "count": 10
}
```

Output (one dataset row per matching profile):

```json
{
  "url": "https://www.linkedin.com/in/sundarpichai",
  "title": "Sundar Pichai - CEO at Google | LinkedIn",
  "description": "CEO at Google · Mountain View, CA",
  "_query": "{\"name\":\"Software Engineer Google\"}"
}
```

**Important Notes:**

- You get results **instantly** — no cookies, no login, no proxy setup
- **Pay only per profile returned** — zero results or a failed run costs you nothing
- Returns up to **50 profiles** per run, from **one** search query per run
- Every row is `url` + `title` + `description` — see [Output Structure](#output-structure) before you build on it
- All data comes from **public sources** only
- Contact: contact@endspec.net

***

### Full Actor Documentation

#### LinkedIn Profile Search

**Search LinkedIn profiles by name, job title, or company — and get results in seconds.** Feed the actor a plain-text query and it returns matching public LinkedIn profiles as clean, structured dataset rows ready for your CRM, spreadsheet, or enrichment pipeline.

***

#### Overview

LinkedIn Profile Search is an Apify Actor that runs a people search against public [LinkedIn](https://www.linkedin.com) profiles and returns each match as a structured row. You give it a free-text query — a person's name, a job title, a company, or any combination of the three — and it returns the profile URL plus a readable title and description line for every match it finds.

It is built for recruiters, sales teams, lead-generation workflows, and market researchers who need to turn a search phrase into a list of LinkedIn profile URLs without running a browser, managing cookies, or maintaining a scraper.

**What this actor does not do:** it does not log in, it does not return private or connection-gated fields, it does not return emails or phone numbers, and it does not enrich a profile beyond the fields listed in [Output Structure](#output-structure). It is a **search** actor — it finds profiles, it does not deep-scrape them.

##### What You Can Do

- **Search by name**: find the public profile URL for a person you can name
- **Search by job title**: pull profiles matching a role such as `Product Manager`
- **Search by company**: pull profiles associated with a company name
- **Combine all three**: `"query": "Jane Smith Data Scientist Stripe"` narrows to a specific person at a specific company
- **Build prospect lists**: return up to 50 profiles per run and export as JSON, CSV, or Excel
- **Feed a pipeline**: use the `url` field as the stable key for downstream enrichment or CRM import

##### Data Availability

**All data returned by this actor is publicly available information.** It only surfaces profile details that LinkedIn members have chosen to make publicly visible on their profiles. No login-gated, connection-gated, or private data is accessed, and no contact details are extracted.

***

#### Actor Input Parameters

The actor accepts the following input parameters:

**query**
• Type: string
• Required: Technically optional in the schema — **but always provide it** (see Important Notes)
• Default: none (the Apify console pre-fills `Software Engineer Google`)
• Description: The people-search phrase. A name, job title, company, or any combination.
e.g., `Software Engineer Google`, `Jane Smith`, `Head of Marketing Stripe`

**count**
• Type: integer
• Required: Optional
• Default: `10` (schema default applied by the Apify console)
• Minimum: `1` — Maximum: `50`
• Description: The maximum number of profiles to return. The actor stops once it has this many results, or earlier if the search runs out of matches.
e.g., `25`

**Important Notes:**

- **Always set `query`.** The input schema does not mark it as required, so a run submitted without it (for example via the API) will **not** fail with a validation error — it will run a meaningless search and return junk or nothing. Treat `query` as mandatory.
- **`count` is a ceiling, not a promise.** If the search has fewer matches than you asked for, you get fewer rows. This is normal and you are only charged for the rows you actually receive.
- **`count` is capped at 50** by the input schema. One run = one query = at most 50 profiles.
- **Omitting `count` from an API call is not the same as leaving it blank in the console.** The console applies the schema default of `10`. A raw API call that omits the field entirely falls back to the actor's internal default of `50`. Set it explicitly if the number matters to your budget.
- **Broader queries return broader matches.** `Software Engineer` matches an enormous population; `Software Engineer Google` is far more useful. Add qualifiers rather than relying on the result count to filter for you.

***

#### Input Examples

##### Example 1: Search by Job Title and Company

```json
{
  "query": "Software Engineer Google",
  "count": 10
}
```

**When to use:** The standard lead-generation case — find people in a given role at a given company.

##### Example 2: Search for a Specific Person

```json
{
  "query": "Sundar Pichai",
  "count": 5
}
```

**When to use:** When you know the person's name and want their public profile URL. Keep `count` low — a name search rarely needs 50 rows, and you pay per row.

##### Example 3: Maximum Result Set for List Building

```json
{
  "query": "Head of Marketing SaaS",
  "count": 50
}
```

**When to use:** Building a prospect list from a broad role query. `50` is the maximum the input schema accepts.

##### Example 4: Query Omitted (Error-Prone — Do Not Do This)

```json
{
  "count": 10
}
```

**Result:** The run does **not** fail with a validation error. Because `query` is not marked required in the schema, the actor performs a search with no meaningful term and will return unusable rows or an empty dataset. Always include `query`.

***

#### Output Structure

The actor writes results to the Apify dataset, one row per matching profile. You can download the dataset as JSON, CSV, Excel, or XML from the Apify console, or fetch it through the Apify API.

##### Successful Output Format

Every returned profile follows this structure:

```json
{
  "url": "string",
  "title": "string",
  "description": "string",
  "_query": "string"
}
```

**Field Descriptions:**

**url**
• Type: string
• Description: The public LinkedIn profile URL. This is the stable identifier to key on downstream. Empty string (`""`) if the match carried no URL.

**title**
• Type: string
• Description: A readable label composed as `<Full name> - <Headline> | LinkedIn`. If the profile has no headline, the format collapses to `<Full name> | LinkedIn`.

**description**
• Type: string
• Description: The profile's headline and location joined by `·`. Either half may be absent — if the profile has only a headline you get just the headline; if it has neither, this is an empty string (`""`).

**\_query**
• Type: string
• Description: A JSON echo of the search this run performed, e.g. `{"name":"Software Engineer Google"}`. Present on every row (success and error) so you can trace a row back to its input when merging datasets from several runs.

**Note on `status`:** successful rows do **not** carry a `status` field. Only error rows do, and its value is always `"error"`. To detect failure, check for the presence of `status` — do not look for `status: "success"`, because the actor never emits it.

##### Error Output Format

When the run cannot complete the search, the actor writes a single error row instead of profile rows:

```json
{
  "status": "error",
  "_query": "string",
  "error": "string"
}
```

**status**
• Type: string
• Description: Always the literal `"error"`. Present only on error rows.

**error**
• Type: string
• Description: A human-readable explanation. For an upstream capacity problem this is the fixed message shown in Example 4 below. For other failures it is a diagnostic string that begins with `Our servers returned HTTP <code>: ` and may carry a short technical detail after the colon.

**You are never charged for an error row.** The `profile-returned` event fires only for rows that contain an actual profile.

***

#### Output Examples

##### Example 1: Full Result — Headline and Location Present

```json
{
  "url": "https://www.linkedin.com/in/sundarpichai",
  "title": "Sundar Pichai - CEO at Google | LinkedIn",
  "description": "CEO at Google · Mountain View, CA",
  "_query": "{\"name\":\"Software Engineer Google\"}"
}
```

Both halves of `description` are populated and `title` carries the headline.

##### Example 2: Partial Result — No Location

```json
{
  "url": "https://www.linkedin.com/in/sample",
  "title": "Alex Rivera - Software Engineer at Google | LinkedIn",
  "description": "Software Engineer at Google",
  "_query": "{\"name\":\"Software Engineer Google\"}"
}
```

The profile has no public location, so `description` contains the headline alone — no `·` separator.

##### Example 3: Minimal Result — Name Only

```json
{
  "url": "https://www.linkedin.com/in/jdoe",
  "title": "Jordan Doe | LinkedIn",
  "description": "",
  "_query": "{\"name\":\"Jordan Doe\"}"
}
```

The profile publishes no headline and no location. `title` collapses to `<Full name> | LinkedIn` and `description` is an empty string. The `url` is still usable.

##### Example 4: Upstream Busy — Fixed Error Message

```json
{
  "status": "error",
  "_query": "{\"name\":\"Software Engineer Google\"}",
  "error": "Our servers are busy right now — please retry shortly. You were not charged."
}
```

Emitted when capacity is temporarily exhausted. Re-run in a few minutes. No charge.

##### Example 5: Other Failure — Diagnostic Error Message

```json
{
  "status": "error",
  "_query": "{\"name\":\"Software Engineer Google\"}",
  "error": "Our servers returned HTTP 403: …"
}
```

Any non-capacity failure produces a message in this form. The text after the colon is a short technical detail and its exact content varies — do not pattern-match on it. Check for the presence of `status` instead. No charge.

##### Example 6: No Results Found (Successful Run, Empty Dataset)

```json
[]
```

If the search matches nothing, the run **succeeds with an empty dataset** — there is no "not found" row and no `status` field to inspect. An empty dataset means zero matches. **No charge.** If this surprises you, the query was probably too narrow or misspelled; see [Best Practices](#best-practices).

***

#### Use Cases

##### For Recruiters and Talent Sourcers

**Candidate Sourcing:** Turn a role-and-company phrase into a list of public LinkedIn profile URLs for a shortlist, then work them in your ATS.

**Example Workflow:**

1. Define the target role and employer, e.g. `Senior Backend Engineer Datadog`
2. Run the actor with `count` set to your shortlist size
3. Export the dataset as CSV
4. Import the `url` column into your ATS or sourcing sheet
5. Review each profile and prioritize outreach

##### For Sales and Lead Generation Teams

**Prospect List Building:** Find decision-makers by title at accounts you already target, and attach a profile URL to every account record.

**Example Workflow:**

1. List your target accounts
2. Run the actor once per account with a query such as `VP Sales <company>`
3. Merge the datasets — `_query` tells you which account each row came from
4. Push `url` and `title` into your CRM as the prospect's profile link and role snapshot
5. Route to the SDR team for sequencing

##### For Marketers and Agencies

**Audience Research:** Map who actually holds a given title across a segment of companies, and use `description` as a fast read on seniority and geography.

**Example Workflow:**

1. Pick the persona you are targeting, e.g. `Head of Growth fintech`
2. Run the actor with `count: 50`
3. Scan the `description` column for role and location patterns
4. Refine your ICP and messaging from what you find

##### For Researchers and Analysts

**Labor-Market Mapping:** Sample public profiles for a role or employer and analyze headline and location distributions.

**Example Workflow:**

1. Run the actor across a set of role queries
2. Aggregate the datasets
3. Split `description` on `·` to separate headline from location
4. Chart role and geography distributions across the sample

##### For Developers

**Pipeline Integration:** Call the actor from your application, then key downstream enrichment on the `url` field.

**Example Workflow:**

1. Trigger the actor via the Apify API with your `query` and `count`
2. Poll for run completion and fetch the dataset
3. Check each row for a `status` field — its presence means the row is an error, not a profile
4. Deduplicate on `url` and store
5. Hand the URLs to your enrichment or scoring step

***

#### Best Practices

##### Writing Good Queries

- **Add qualifiers, don't widen `count`** — `Product Manager Airbnb` beats `Product Manager` with `count: 50`. The result count does not filter for relevance.
- **Spell company names as LinkedIn shows them** — the query is matched as text, so a misspelled employer returns nothing.
- **One query per run** — the actor takes a single `query`. To cover several roles or accounts, run it once per query and merge the datasets using `_query`.
- **Start small** — test with `count: 5` before committing to `count: 50` across many runs.

##### Handling Results

- **Detect errors by the presence of `status`, not by `status: "success"`** — successful rows have no `status` field at all.
- **Never pattern-match on `error` text** — only the capacity message is fixed. Other messages vary.
- **Treat an empty dataset as "no matches"** — a successful run with zero rows is a valid outcome, not a failure.
- **Expect fewer rows than `count`** — this is normal when the search runs out of matches.
- **Key on `url`, not `title`** — `title` is a composed display string and its shape changes when a profile has no headline.
- **Handle empty strings** — `url`, `title`, and `description` can each be `""` when the underlying profile is sparse.
- **Log the Apify run ID** — include it if you contact support.

##### Data Usage

- **Verify before acting** — public profiles change; a headline captured today may be stale next month.
- **Respect privacy** — use profile data for legitimate business purposes only.
- **Follow anti-spam and data-protection law** — GDPR, CAN-SPAM, and local equivalents apply to how you use what you collect.
- **Honor opt-outs** — remove people who ask to be removed from your lists.

***

#### Cost, Performance, and Limits

**Pricing model: pay per event.** The actor charges one `profile-returned` event for each profile row written to the dataset. The launch price is **$0.0070 per profile returned** — check the actor's Pricing tab for the current rate, which is authoritative.

**You are not charged for:**

- Runs that return zero matches (empty dataset)
- Error rows of any kind
- Any row that is not an actual profile

**Performance:**

- Results are returned in seconds — there is no browser, no page rendering, and no proxy negotiation.
- Results are fetched in pages of 10, so a run makes at most `ceil(count / 10)` upstream requests — `count: 10` is one request, `count: 50` is five.
- Runs are lightweight; the default memory allocation is sufficient.

**Limits:**

- **One search query per run.**
- **Maximum 50 profiles per run** (input-schema cap).
- **No pagination beyond 50** — to go deeper, narrow the query rather than trying to page further.
- **Fields are fixed** — `url`, `title`, `description`, `_query`. The actor does not return emails, phone numbers, connection counts, work history, or profile photos.
- **Capacity is shared** — during a burst you may receive the busy error row. Re-run shortly; you were not charged.

***

#### Data Sources and Legality

**All data returned by this actor is publicly available information** that LinkedIn members have made publicly visible on their profiles. The actor does not log in, does not bypass access controls, and does not return private, connection-gated, or contact information.

**What this means:**

- Every field returned is already publicly visible on the profile
- No credentials, cookies, or session tokens are involved
- No private or restricted data is accessed

**Your responsibility:** you are responsible for complying with all applicable laws, regulations, and terms of service in your jurisdiction when collecting and using this data — including GDPR, CCPA, and any anti-spam rules that govern your outreach. Personal data of EU/UK residents carries obligations regardless of whether it was published publicly. This README is not legal advice; if your use case is sensitive, take advice before you run at scale.

***

#### Frequently Asked Questions

**Q: Why do my successful rows have no `status` field?**
A: By design — the actor only sets `status` on error rows, where it is always `"error"`. Check whether `status` exists rather than testing for `status: "success"`, which the actor never emits.

**Q: I asked for 50 profiles and got 12. Why?**
A: `count` is a maximum. The search had 12 matches. You were charged for 12.

**Q: My run finished successfully but the dataset is empty. Is that an error?**
A: No. Zero matches is a successful outcome with an empty dataset and no charge. Usually the query is too narrow or a name is misspelled — broaden it or check the spelling.

**Q: Can I search multiple names or companies in one run?**
A: Not in a single run — the actor takes one `query`. Run it once per query and merge the datasets; the `_query` field on every row tells you which run produced it.

**Q: Can I get email addresses or phone numbers?**
A: No. This actor returns `url`, `title`, and `description` only. It is a profile-search actor, not a contact-enrichment actor.

**Q: Why is `description` sometimes empty?**
A: It is built from the profile's headline and location. If the profile publishes neither publicly, the field is an empty string. The `url` is still valid.

**Q: What does the `title` field actually contain?**
A: A composed display string: `<Full name> - <Headline> | LinkedIn`, collapsing to `<Full name> | LinkedIn` when there is no headline. It is for display — key your data on `url`.

**Q: I got "Our servers are busy right now". What do I do?**
A: Wait a few minutes and re-run. It means capacity was momentarily exhausted. You were not charged.

**Q: Do I need LinkedIn cookies, a login, or a proxy?**
A: No. There is nothing to configure — supply a query and run it.

**Q: Can I use this actor commercially?**
A: Yes. The data is publicly available. You remain responsible for how you use it — see [Data Sources and Legality](#data-sources-and-legality).

**Q: How fresh are the results?**
A: They reflect the profiles as currently published. Because people update their profiles, re-run periodically for lists you rely on.

***

#### Contact & Support

**Questions? Need help? We're here for you.**

For questions, technical support, feature requests, or any inquiry about LinkedIn Profile Search, reach out:

**Email:** contact@endspec.net

**Response Time:** We respond within 24 hours on business days.

**What to include in your inquiry:**

- A description of your question or issue
- The Apify run ID (if applicable)
- The exact input you used
- Any `status` / `error` values from the dataset rows
- What you expected versus what you received

You can also report issues through the **Issues** tab on this actor's Apify page.

***

#### Related Actors

- [YouTube Instant Email Scraper](https://apify.com/endspec/youtube-instant-email-scraper) — extract public contact emails from YouTube channels for lead generation.
- [YouTube Channel Contacts Extractor](https://apify.com/endspec/youtube-channel-contacts-extractor) — get emails, socials, and website URLs for any YouTube channel instantly.
- [Instagram Instant Media Scraper](https://apify.com/endspec/instagram-instant-media-scraper) — pull public media data from Instagram profiles.

***

*Last Updated: July 2026*

# Actor input Schema

## `query` (type: `string`):

Name, job title, company, or combination (e.g. 'John Doe Software Engineer Google')

## `count` (type: `integer`):

Max profiles to return (1-50)

## Actor input object example

```json
{
  "query": "Software Engineer Google",
  "count": 10
}
```

# 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 = {
    "query": "Software Engineer Google"
};

// Run the Actor and wait for it to finish
const run = await client.actor("endspec/linkedin-instant-profile-search").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 = { "query": "Software Engineer Google" }

# Run the Actor and wait for it to finish
run = client.actor("endspec/linkedin-instant-profile-search").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 '{
  "query": "Software Engineer Google"
}' |
apify call endspec/linkedin-instant-profile-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,endspec/linkedin-instant-profile-search"
        }
    }
}

```

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/ySBXpd89jQDY9mLJr/builds/34adIoeqoOuUoe2HL/openapi.json
