# Company Enrichment by Domain: Firmographics, Contacts & Tech (`larkmoor/company-enrichment`) Actor

Enrich company domains with facts from each company's own website and public registries: name, legal name, description, logo, founding year, address, emails, phones, LinkedIn and socials, tech stack, email provider, domain age and hiring signal. Failed lookups are free.

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

## Pricing

from $1.70 / 1,000 enriched companies

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: Firmographics, Contacts, Socials & Tech Stack

Give it a list of company domains and get back **one clean company profile per domain**: company name and legal name, description, **logo**, founding year, employee count (when the company publishes it), **headquarters address**, business **emails and phones**, **LinkedIn**, X, Facebook, Instagram, YouTube, TikTok and GitHub profiles, the **tech stack** (CMS, e-commerce, analytics, hosting), the **email provider**, the **domain age** and a **hiring signal** (careers page plus the job board the company uses).

Every fact comes from the **company's own public website** and the **public domain registry (RDAP)**. No people databases, no guessed revenue figures, no login walls. That makes it a low-cost, transparent alternative to Clearbit, ZoomInfo or Apollo company enrichment for CRMs, lead lists and market maps: **$2 per 1,000 companies**, and failed lookups are free.

### What does it return?

**Identity**

- `companyName` (schema.org, `og:site_name`, legal notices or the page title, generic words like "Home" dropped), `legalName` (e.g. "Stripe, LLC", "Notion Labs, Inc.")
- `description`, `logo` (schema.org logo first, then app icon, then social image), `favicon`
- `foundingYear`, `employees`, `organizationType`, `industry`: only when the company states them in its structured data. Empty means the site does not say, not that we guessed.

**Location and contact**

- `address` and `addressParts` (street, city, region, postal code, country), `country`, `language`
- `primaryEmail` and `emails` (business addresses found on the homepage, contact, about, legal and team pages, with the page each one came from in `sources.emailSources`)
- `primaryPhone` and `phones`
- `vatId`, `registrationNumber` and `registrationType` from European legal notices (Impressum, mentions légales, UK company number)

**Social profiles**

- `linkedin`, `twitter`, `facebook`, `instagram`, `youtube`, `tiktok`, `github`, `pinterest`, plus `crunchbase` and `wikipedia` when the company links them in its own `sameAs` data. Share buttons are ignored.

**Technology**

- `technologies` (all detected), `cms`, `ecommerce`, `analytics` (including ad pixels), `hosting`
- `emailProvider` from the domain's MX records (Google Workspace, Microsoft 365, Zoho, Proofpoint and others)

**Domain and growth signals**

- `domainCreatedAt`, `domainAgeYears`, `registrar` from RDAP, the official successor of WHOIS
- `hiringSignal`, `careersPage`, `jobBoard`, `jobBoardProvider`, `jobBoardSlug`: the company's careers page and its job board on Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters, BambooHR, Recruitee, Personio, Teamtailor, Breezy HR, Jobvite, iCIMS, Rippling, JazzHR, Pinpoint or Gem

**Quality**

- `completeness`: the share of nine core facts found (name, description, logo, address, email, phone, LinkedIn, founding year, employees), so you can sort and filter
- `blocked` and `error` for sites that refused automated reads

### Who is it for?

- **Sales and RevOps teams** filling empty CRM fields (logo, LinkedIn, phone, HQ, tech) for accounts that only have a domain.
- **Lead generation**: turn a list of domains from a directory, an event or a sitemap into qualified rows, then filter by tech stack, country or hiring.
- **Recruiters and staffing agencies**: find which companies are hiring and which job board they use, then pull the open roles with a job-board actor.
- **Investors and analysts** building market maps: founding year, domain age, location and stack for hundreds of companies at once.
- **SaaS products** that pre-fill a new signup's company profile from the email domain.

### Input

| Field | What it does |
|---|---|
| `domains` | domains or URLs, one per line (`hubspot.com`, `https://www.notion.so`) |
| `maxPagesPerSite` | pages read per site for contacts (homepage, contact, about, legal, team), default 5 |
| `includeTechStack` | detect technologies and the email provider, default on |
| `includeHiringSignal` | find the careers page and job board, default on |
| `includeDomainAge` | RDAP registration date and registrar, default on |
| `skipFailed` | leave failed domains out instead of returning a free row with the reason |
| `concurrency` | companies processed in parallel, default 6 |
| `maxResults` | cap on the number of domains |

```json
{
  "domains": ["hubspot.com", "notion.so", "mailchimp.com", "stripe.com"],
  "maxPagesPerSite": 5,
  "includeTechStack": true,
  "includeHiringSignal": true,
  "includeDomainAge": true
}
```

### Output

One row per company (a real run, shortened):

```json
{
  "input": "hubspot.com",
  "domain": "hubspot.com",
  "website": "https://www.hubspot.com/",
  "reachable": true,
  "companyName": "HubSpot",
  "description": "HubSpot is an AI-powered customer platform with software for marketing, sales, customer service, content management, operations, and commerce.",
  "logo": "https://www.hubspot.com/hubfs/HubSpot_Logos/HSLogo_color.svg",
  "favicon": "https://www.hubspot.com/hubfs/HubSpot_Logos/HubSpot-Inversed-Favicon.png",
  "foundingYear": 2006,
  "organizationType": "Organization",
  "address": "2 Canal Park, Cambridge, MA, 02141, US",
  "addressParts": {
    "street": "2 Canal Park",
    "city": "Cambridge",
    "region": "MA",
    "postalCode": "02141",
    "country": "US",
    "full": "2 Canal Park, Cambridge, MA, 02141, US"
  },
  "country": "US",
  "language": "en",
  "primaryPhone": "18884827768",
  "phones": [
    "18884827768",
    "+35315187500",
    "+6569556000",
    "+61291648000"
  ],
  "linkedin": "https://www.linkedin.com/company/hubspot",
  "twitter": "https://x.com/HubSpot",
  "facebook": "https://www.facebook.com/hubspot",
  "instagram": "https://www.instagram.com/hubspot",
  "youtube": "https://youtube.com/user/HubSpot",
  "tiktok": "https://www.tiktok.com/@HubSpot",
  "wikipedia": "https://en.wikipedia.org/wiki/HubSpot",
  "technologies": [
    "Cloudflare",
    "Cloudflare Web Analytics",
    "Facebook Pixel",
    "Google Analytics"
  ],
  "cms": [
    "HubSpot CMS"
  ],
  "analytics": [
    "Facebook Pixel",
    "Google Analytics",
    "Hotjar",
    "LinkedIn Insight",
    "TikTok Pixel"
  ],
  "emailProvider": "Google Workspace",
  "hosting": [
    "Cloudflare"
  ],
  "careersPage": "https://www.hubspot.com/careers",
  "hiringSignal": true,
  "domainCreatedAt": "2005-02-06T20:02:28Z",
  "registrar": "MarkMonitor Inc.",
  "domainAgeYears": 21.7,
  "completeness": 0.78,
  "blocked": false
}
```

Download the dataset as CSV, Excel, JSON or HTML, or read it through the API. The "Companies" table view shows the most useful columns first.

### How much does it cost?

You pay **$0.002 per enriched company** ($2 per 1,000) plus a one-time $0.001 actor start. A company counts as enriched when at least two core facts were found. Domains that do not answer, block automated reads or have nothing public come back as free rows with the reason in `error`. Higher Apify plans get automatic volume discounts (up to 15% off).

- **50 target accounts** before a sales sprint: about **$0.10**.
- **2,000 domains** from a trade-show exhibitor list: about **$4**.
- **20,000 CRM accounts** with empty fields: about **$40**, compared with hundreds or thousands of dollars a year for a data subscription.

Runs work at 512 MB; most sites take 1 to 3 seconds each.

### FAQ

**Where does the data come from?** From each company's own website (structured data, legal notice, contact and about pages, the homepage's links and scripts), its public DNS records and the public RDAP domain registry. Nothing is bought, inferred from third-party databases or invented.

**Is this legal?** The actor reads pages that every company publishes for every visitor, respects robots.txt (a site that disallows bots is skipped and not charged) and never logs in. It collects business contact details that companies publish themselves. If you use the emails for outreach, follow the rules that apply to you (GDPR, CAN-SPAM, CASL), such as offering an opt-out.

**Why are employees or founding year empty?** Many companies do not publish them in their structured data. We return them only when the company states them. Empty fields are never filled with estimates.

**Why do some big sites fail?** A few sites put every visitor through a bot check. The actor retries once through a datacenter proxy; if the site still refuses, the row is free and marked `blocked`.

**Does it find personal emails of employees?** No. It returns the addresses a company shows on its own pages (sales@, info@, press@, sometimes a named contact on a contact page). It does not guess or verify people's emails.

**Can I give it company names instead of domains?** Not yet: it needs a domain or URL.

### Integrations

Schedule it, call it from the Apify API, or connect it to Make, Zapier, n8n, Google Sheets, HubSpot, Salesforce or a webhook to enrich every new account automatically.

### Changelog

- **0.1** (Nov 2026): first release: identity, logo, address, emails, phones, socials, tech stack, email provider, RDAP domain age, hiring signal with 17 job boards, completeness score, free failed lookups.

# Actor input Schema

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

Company domains or website URLs, one per line (e.g. hubspot.com). Duplicates are removed. The actor reads only these companies' own public websites plus the public domain registry (RDAP).

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

Stop after this many domains. Default 1000.

## `maxPagesPerSite` (type: `integer`):

How many pages of each site to read (homepage first, then contact, about, legal and team pages). More pages find more emails and phones; 5 is a good balance.

## `includeTechStack` (type: `boolean`):

Detect CMS, e-commerce platform, analytics, hosting and the email provider (from DNS MX records).

## `includeHiringSignal` (type: `boolean`):

Find the careers page and the job board the company uses (Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters, BambooHR, Personio and more).

## `includeDomainAge` (type: `boolean`):

Look up the domain's registration date and registrar in the public RDAP registry (the open successor of WHOIS).

## `skipFailed` (type: `boolean`):

By default a domain that cannot be read gets a free row with the reason in `error`. Turn this on to leave those rows out.

## `concurrency` (type: `integer`):

Companies enriched at the same time (1-10).

## Actor input object example

```json
{
  "domains": [
    "hubspot.com",
    "notion.so",
    "mailchimp.com",
    "stripe.com"
  ],
  "maxResults": 1000,
  "maxPagesPerSite": 5,
  "includeTechStack": true,
  "includeHiringSignal": true,
  "includeDomainAge": true,
  "skipFailed": false,
  "concurrency": 6
}
```

# Actor output Schema

## `results` (type: `string`):

One enriched company per row in the run's default dataset (download as CSV, Excel or JSON).

# 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",
        "notion.so",
        "mailchimp.com",
        "stripe.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("larkmoor/company-enrichment").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",
        "notion.so",
        "mailchimp.com",
        "stripe.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("larkmoor/company-enrichment").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",
    "notion.so",
    "mailchimp.com",
    "stripe.com"
  ]
}' |
apify call larkmoor/company-enrichment --silent --output-dataset

```

## MCP server setup

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

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/scbcrA31ZIFgTEchP/builds/xTTC0hneAWyntAckO/openapi.json
