# Company Enrichment by Domain: LinkedIn, Social Links & Logo (`earlytern/company-enrichment-by-domain`) Actor

Turn company domains into one row per company: LinkedIn company page, Facebook, X, Instagram, YouTube, TikTok and GitHub accounts, logo, name, description, contact and careers page and job board system. Reads only the company's own website. No emails or phone numbers.

- **URL**: https://apify.com/earlytern/company-enrichment-by-domain.md
- **Developed by:** [earlytern](https://apify.com/earlytern) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 company profile founds

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?

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

## Company Enrichment by Domain: LinkedIn, Social Links & Logo

Turn a list of **company domains** into **one clean row per company**: the **LinkedIn company page**, the company's
**Facebook, X (Twitter), Instagram, YouTube, TikTok, GitHub, Threads and Pinterest** accounts, the **logo**, company
name and description, the **contact page**, the **careers page** and the **job board system** the company hires with
(Greenhouse, Lever, Ashby, Workday and more). Paste 2 domains or 10,000, get a table ready for your CRM, spreadsheet
or lead list. You pay only for companies where something was found.

### What does Company Enrichment by Domain do?

- **Finds the company's own channels**: reads the links the company itself puts on its website (organization data,
  header, footer), so the LinkedIn page and social accounts are the official ones, not look-alikes.
- **Filters out the noise**: personal LinkedIn profiles (`/in/`), "share this" buttons, single posts and videos are
  never returned. Accounts whose name does not match the company (a founder's own account, a parent company) are
  listed in `possiblyPersonal`, so you can check them before use.
- **Logo, name and description** from the website's own tags and organization data.
- **Contact and careers pages**, plus the **job board system** in use and a link to the job board: useful for
  recruiting, sales to hiring companies, and for feeding a job scraper.
- **Says where each link came from** (`sources`: organization data, header, footer, page body or a subpage) and, when
  nothing was found, **why** (`status` and `message`).
- **Light and polite**: plain HTTP requests, no browser; reads the home page and at most two more pages per website,
  always obeys robots.txt, and never logs in.

### Who uses it?

- **Sales and RevOps teams** filling empty LinkedIn and social columns in a CRM or a lead list before outreach.
- **Lead generation and data agencies** building company lists from domains.
- **Recruiters and HR tech** finding which companies hire through which job board system, and their careers pages.
- **Marketers and researchers** collecting logos and official accounts of competitors, partners or customers.
- **AI agents** that need a short, structured company card from a domain.

### How to use it

1. Click **Try for free**.
2. In **Domains**, paste company domains or website addresses, one per line: `stripe.com`, `https://www.hubspot.com`.
3. Click **Start**. Download the results as JSON, CSV or Excel, or use the API. The **Companies** view shows one row
   per domain.

Options: turn off **Open contact and about pages** to read only the home page (faster, a little less found), and turn
off **Find careers page and job board** if you do not need hiring data.

### Use with AI agents (MCP)

AI assistants and AI agents can call this Actor through Apify's MCP server at [mcp.apify.com](https://mcp.apify.com)
or through the Apify API. Send the whole list of domains in one call and read one row per domain. Questions it answers
well:

- "What is the LinkedIn page of example.com?" Read `linkedinUrl`.
- "Find the official social accounts and logo of these 200 companies." Read `socials` and `logoUrl`; skip or check the
  networks listed in `possiblyPersonal`.
- "Which job board does example.com use?" Read `atsProvider`, `atsUrl` and `careersPageUrl`.

Only `domains` is required. Rows with `status` other than `found` are free and say why in `message`.

### Input example

```json
{
  "domains": ["stripe.com", "https://www.hubspot.com"],
  "followContactPages": true,
  "detectCareers": true
}
```

### Output example

A real row from a test run:

```json
{
  "input": "stripe.com",
  "domain": "stripe.com",
  "status": "found",
  "message": null,
  "websiteUrl": "https://stripe.com/",
  "companyName": "Stripe",
  "description": "Stripe is a financial services platform that helps all types of businesses accept payments, build flexible billing models, and manage money movement.",
  "logoUrl": "https://images.stripeassets.com/fzn2n1nzq965/1hgcBNd12BfT9VLgbId7By/01d91920114b124fb4cf6d448f9f06eb/favicon.svg",
  "linkedinUrl": "https://www.linkedin.com/company/stripe",
  "socials": {
    "facebook": "https://www.facebook.com/StripeHQ",
    "x": "https://x.com/stripe",
    "instagram": "https://www.instagram.com/stripehq",
    "youtube": "https://www.youtube.com/@stripe",
    "tiktok": null,
    "github": "https://github.com/stripe",
    "threads": null,
    "pinterest": null
  },
  "sources": { "linkedin": "jsonld", "facebook": "jsonld", "x": "jsonld", "instagram": "jsonld", "youtube": "jsonld", "github": "jsonld" },
  "possiblyPersonal": [],
  "contactPageUrl": "https://stripe.com/contact/sales",
  "careersPageUrl": "https://stripe.com/careers",
  "atsProvider": null,
  "atsUrl": null,
  "pagesRead": 2,
  "checkedAt": "2026-11-02T21:04:56.266Z"
}
```

#### Status values

| `status` | Meaning | Charged |
|---|---|---|
| `found` | The website links at least one company channel (LinkedIn page or social account) | Yes |
| `not_found` | The website was read, but links no company channel, or the domain is parked or for sale | No |
| `needs_browser` | The home page is built with JavaScript in the browser, so its links could not be read | No |
| `blocked` | The website refused the request or shows a bot check | No |
| `robots_txt` | The website's robots.txt does not allow reading it | No |
| `unreachable` | The domain does not exist, did not answer, or answered with an error | No |
| `not_allowed` | A large platform, an IP address, a local or private network address; never contacted | No |
| `invalid` | The line is not a domain or website address | No |

Job board systems recognised in `atsProvider`: greenhouse, lever, ashby, workable, workday, smartrecruiters, bamboohr,
recruitee, teamtailor, personio, jobvite, icims, breezy, jazzhr, taleo, successfactors, pinpoint, rippling, join and
homerun. Many large companies run their own careers website; then `careersPageUrl` is filled and `atsProvider` stays
empty.

### How much does it cost?

You pay only for companies where at least one channel was found. No start fee. Prices per 1,000 companies found, by
Apify plan:

| Event | Free | Bronze | Silver | Gold and up |
|---|---|---|---|---|
| Company profile found | $2.00 | $1.70 | $1.40 | $1.20 |

- **Free**: domains with nothing found, blocked or unreachable websites, websites that need a browser, invalid lines
  and duplicates (the same domain twice is checked once).
- Opening the contact, about and careers pages costs nothing extra.
- Set a **maximum cost per run** and the Actor stops cleanly before going over it; the run's status message says how
  many domains were not checked.

Example on the Free plan: enriching a list of 5,000 domains where 4,000 companies are found costs $8.00.

### FAQ

**Why is the LinkedIn page empty for some companies?** The Actor only returns links the company itself publishes on
its website. If the website does not link its LinkedIn page, `linkedinUrl` stays empty rather than guessed.

**Does it visit LinkedIn or the social networks?** No. It reads only the company's own website and returns the
addresses of the accounts. Large platforms are never contacted, also not when given as input.

**Why `blocked` or `needs_browser`?** Some websites refuse automated requests or only work in a browser. The Actor
does not try to get past blocking and does not run a browser; such rows are free.

**What does `possiblyPersonal` mean?** The account linked from the website has a name that does not match the company
(for example a founder's personal account or a parent company's page). It is returned, so you can decide; most CRMs
should check it first.

**Does it return emails or phone numbers?** No. It links to the contact page instead. Emails, phone numbers and street
addresses found in names and descriptions are removed.

**What about parked domains?** A domain that shows a "for sale" or parking page, or redirects to a domain marketplace,
gets `not_found` and is free: its links belong to the marketplace, not to a company.

### Limits

- Up to 10,000 domains per run; 10 websites are read at the same time.
- Per website: robots.txt, the home page and at most two more pages (careers, about or contact), with a pause between
  requests; a robots.txt Crawl-delay is always obeyed. When it asks for a long pause, the Actor reads fewer pages of
  that website instead of waiting.
- Websites are read over https, or over http when https does not answer.
- Pages larger than 3 MB are read up to 3 MB.
- The run stops in time to save its results before the run timeout; for very large lists give the run more time.

### Is it legal?

The Actor reads only public pages of company websites, always obeys robots.txt, never logs in and never tries to get
past blocking. It keeps only the fields shown above: no page text is stored, personal LinkedIn profiles are never
returned, and no emails or phone numbers are collected. The output is business data: the public channels a company
publishes about itself. For one-person businesses a "company" account may belong to a person; you are responsible for
how you use the data and for following the privacy laws that apply to you (such as the GDPR).

### Questions and feedback

Open an issue on the **Issues** tab.

# Actor input Schema

## `domains` (type: `array`):

Company domains or website addresses, one per line, for example stripe.com or https://www.hubspot.com. Up to 10,000 per run. The same domain twice is checked once.

## `followContactPages` (type: `boolean`):

When the home page has no LinkedIn link or fewer than two company accounts, also read the about and contact pages (at most two more pages per website). No extra charge.

## `detectCareers` (type: `boolean`):

Find the careers page and the job board system the company uses (Greenhouse, Lever, Ashby, Workday and others). May read the careers page when the home page does not show the system.

## Actor input object example

```json
{
  "domains": [
    "hubspot.com",
    "stripe.com"
  ],
  "followContactPages": true,
  "detectCareers": true
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "domains": [
        "hubspot.com",
        "stripe.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("earlytern/company-enrichment-by-domain").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 = { "domains": [
        "hubspot.com",
        "stripe.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("earlytern/company-enrichment-by-domain").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 '{
  "domains": [
    "hubspot.com",
    "stripe.com"
  ]
}' |
apify call earlytern/company-enrichment-by-domain --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,earlytern/company-enrichment-by-domain"
        }
    }
}
```

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/VxkJrdps3wGbQbHbU/builds/V4pPixRuQ7b8KigFF/openapi.json
