# Y Combinator Companies Scraper - Founders & New Startups (`neverempty/yc-companies-monitor`) Actor

Company data from Y Combinator company pages: batch, status, team size, location, tags, website, social links and founders with LinkedIn URLs. Read a list, filter the whole directory, or monitor it and get only newly listed startups.

- **URL**: https://apify.com/neverempty/yc-companies-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 company 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?

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

## Y Combinator Companies Scraper - Founders & New Startups

Company data from the public **Y Combinator company pages** (`ycombinator.com/companies/<slug>`), one row per company: name, batch, status, one-liner, website, team size, year founded, location, country, tags, description, social links, group partner and the founders shown on the page with their titles, bios and public LinkedIn / X links.

Three ways to use it:

1. **A list** - paste company page addresses or slugs and get one row for each.
2. **The whole directory with filters** - the Actor takes the company list from YC's public sitemap (about 6,300 company pages on 2026-10-05), opens the pages and returns the companies that match your filters (batch, status, country, tag, team size).
3. **Monitoring** - run it on a schedule and get **only the companies newly added to the directory** since the last run.

No login, no cookies. Only what the public company page shows is returned; nothing is added from other sources, so there are **no email addresses**.

### What you get

| Column | Meaning |
|---|---|
| `name`, `slug`, `companyId`, `ycUrl` | The company, its slug in the directory, YC's numeric ID and the page address |
| `batch`, `batchCode` | Batch as written on the page (`Winter 2009`) and its short form (`W09`) |
| `ycStatus` | Status as written on the page (`Active`, `Public`, `Acquired`, `Inactive`) |
| `oneLiner`, `longDescription` | The one-line pitch and the description |
| `website` | Company website |
| `teamSize`, `yearFounded` | As shown on the page |
| `location`, `city`, `country` | Location text, city and two-letter country code |
| `tags` | Industry tags on the page |
| `founderNames`, `founderCount`, `founders` | Founders listed on the page; each entry in `founders` has `name`, `title`, `bio`, `linkedinUrl`, `twitterUrl`, `isActive` |
| `groupPartner`, `groupPartnerUrl` | The YC group partner named on the page |
| `linkedinUrl`, `twitterUrl`, `facebookUrl`, `crunchbaseUrl`, `githubUrl` | Company links on the page |
| `smallLogoUrl` | Small logo image |
| `sitemapLastModified` | The page's last-modified date in YC's sitemap (whole-directory and monitoring runs) |
| `change`, `previousCheckedAt` | Monitoring runs only: `new-company`, and the time of the earlier run that last recorded companies for these filters (the first run, or the last run that found a new page) |
| `input`, `scrapedAt`, `status` | What you typed, when the page was read, `ok` for a company row |

A value that is not on the page is `null`, never 0 or an empty string. Team size, status and location are what the company page shows at the moment of the read; YC and the companies update them at their own pace.

Before a row is returned, the slug the page itself reports is compared with the slug that was requested. If they differ, no data is returned for that line (a free `slug-mismatch` row instead).

### Input

- **`companies`** - one per line: `https://www.ycombinator.com/companies/airbnb` or just `airbnb`. Up to 1,000 lines. When this is filled in, only these companies are read; the options below are not applied.
- **`allCompanies`** - read the directory from its sitemap, most recently updated pages first.
- **`batches`**, **`statuses`**, **`countries`**, **`tags`**, **`minTeamSize`**, **`maxTeamSize`** - filters for the whole-directory and monitoring modes. Inside one filter any value may match; different filters must all match. They are written as on the company page (`Winter 2025` or `W25`, `Active`, `US`, `Fintech`) and are not case-sensitive. A company with no team size on its page does not match a team-size filter.
- **`maxCompanies`** - stop when this many companies have been returned (default 100).
- **`maxPagesToRead`** - stop after reading this many company pages, matched or not (default 1,000, at most 10,000 per run).
- **`monitoringMode`**, **`resetMonitoringState`** - see below.
- **`useProxy`** - requests go directly to www.ycombinator.com; a residential proxy is tried once per refused request, at most three times in a run, only when the site answers HTTP 403 or 429. After a refusal the run stops sending requests and says what it did not read.

The filters are applied to each company page **after it has been read**: YC's filtered directory list (`/companies?...`) is disallowed by its robots.txt and is not used. That is why a filtered run reads more pages than it returns, and why pages that did not match have a small charge (below).

### Monitoring mode

Turn **monitoringMode** on, leave `companies` empty, and schedule the Actor.

- The **first run** with a given set of filters only remembers the company pages listed in the sitemap at that moment. It reads no company page, returns one free `baseline-saved` row and charges nothing. To get the companies that are already listed, run once with monitoring off.
- **Later runs** read only the company pages that were not in the sitemap before. Those that match your filters come back as rows with `change: "new-company"`.
- Every later run is charged one monitoring check (`sitemap-checked`) for reading the sitemap and comparing it with the remembered pages. A run with no new company page returns one free `no-new-companies` row and is charged only that check.
- A new company that could not be read, or that was cut off by `maxCompanies`, `maxPagesToRead` or a charge limit, is not remembered; it still counts as new.

Companies are remembered per set of filters, so two schedules with different filters do not affect each other. Do not run two schedules with the same filters at the same moment: the platform's key-value store has no atomic update, so two runs finishing together can overwrite each other's record and return the same company twice.

Monitoring detects pages that are new in the sitemap. A company that already existed and whose page moved to a new slug appears as a new page too (use `batch` and `yearFounded` to tell). If a run finds that more than a quarter of the sitemap is not remembered, it treats the earlier record as incomplete: it reads nothing, charges nothing and asks for a reset. It does not report changes to a company that was already listed (a new team size, a status change).

### What is charged

- **`company-returned`** - one per company row.

- **`company-checked`** - whole-directory and monitoring modes only: one per company page that was read but does not match your filters. A run with no filter, and a run on a list of `companies`, never charge this.

- **`sitemap-checked`** - monitoring mode only: one per run that read the sitemap and compared it with the remembered company pages. The first monitoring run (which only remembers the current list) is not charged.

There is no start fee and no monthly fee. Rows that explain why nothing was returned are free: `no-such-company`, `slug-mismatch`, `invalid-input`, `duplicate-input`, `unreadable`, `blocked`, `robots-disallowed`, `no-match`, `no-new-companies`, `baseline-saved`, `not-read`, `budget-reached`.

A filtered run over the whole directory reads every page until `maxCompanies` or `maxPagesToRead` is reached, so its cost is bounded by `maxPagesToRead`: each page read is charged once, either as a row or as a check. If you set a maximum total charge for a run, the Actor reads a page only while the limit has room for it, and adds a free `not-read` row saying how many pages it did not read.

### How it reads

- `robots.txt` of www.ycombinator.com is read at the start of every run and followed (rules for `User-agent: *`). Only `/companies/sitemap.xml` and `/companies/<slug>` are requested.
- Two requests at a time with a pause between them; a failed request is retried once.
- If a page is refused (HTTP 403 / 429 or a verification page), or three pages in a row cannot be read, the run stops sending requests and reports what it did not read.
- A full pass over the directory takes roughly an hour; raise the run timeout if you read more than a few thousand pages in one run.

### Limits

- Data comes only from company pages. Jobs, news and launch posts are not included.
- The filters need each page to be read; there is no faster path for "all companies of one batch".
- This Actor is not affiliated with or endorsed by Y Combinator. You are responsible for how you use the data, including Y Combinator's terms of use and privacy laws that apply to the founder names and profile links.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

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

Y Combinator company pages to read: https://www.ycombinator.com/companies/airbnb, or just the slug (airbnb). One company per line, up to 1,000 lines. Each company page that is read and returned is one charged row. A slug with no company page comes back as a "no-such-company" row that is not charged. Leave this empty to use "Read the whole directory" or monitoring mode instead.

## `allCompanies` (type: `boolean`):

Used only when "Company pages or slugs" is empty. The Actor reads the company list from the public sitemap (/companies/sitemap.xml, about 6,300 companies on 2026-10-05), most recently updated pages first, opens company pages one by one and returns those that match the filters below. Each company returned is charged as one row (company-returned). Each company page that was read but does not match your filters is charged as one check (company-checked), because the filters can only be applied after a page has been read. With no filter every page read is a row and no check is charged.

## `batches` (type: `array`):

Keep only companies of these batches, written as on the company page: "Winter 2009", "Summer 2024", "Spring 2025" (the short form W09, S24, P25 also works). Not case-sensitive. Whole-directory and monitoring mode only.

## `statuses` (type: `array`):

Keep only companies with these statuses, written as on the company page: Active, Public, Acquired, Inactive. Whole-directory and monitoring mode only.

## `countries` (type: `array`):

Keep only companies in these countries, as two-letter codes as on the company page: US, GB, IN, CA. Whole-directory and monitoring mode only.

## `tags` (type: `array`):

Keep only companies that have at least one of these tags, written as on the company page: Fintech, SaaS, Artificial Intelligence, Marketplace. Not case-sensitive. Whole-directory and monitoring mode only.

## `minTeamSize` (type: `integer`):

Keep only companies whose team size on the page is at least this number. Companies with no team size on their page do not match. Whole-directory and monitoring mode only.

## `maxTeamSize` (type: `integer`):

Keep only companies whose team size on the page is at most this number. Companies with no team size on their page do not match. Whole-directory and monitoring mode only.

## `maxCompanies` (type: `integer`):

Whole-directory and monitoring mode: the run stops when this many company rows have been returned. Not applied to a list in "Company pages or slugs" (every listed company is read).

## `maxPagesToRead` (type: `integer`):

Whole-directory and monitoring mode: the run stops after reading this many company pages, whether or not they matched the filters. This bounds what filters can cost: at most this many pages are charged, each either as a row or as a check.

## `monitoringMode` (type: `boolean`):

Watches the directory sitemap. The first run with a given set of filters only remembers the company pages that are listed now: it reads no company page, returns no company and charges nothing. Later runs are charged one monitoring check each (sitemap-checked) for reading the sitemap and comparing it; they read only company pages that were not in the sitemap before, return those that match the filters (company-returned) and charge one check (company-checked) for each new page that was read but does not match. A run with no new company page is charged only the monitoring check. A page that is new in the sitemap counts as new, including an existing company whose page moved to a new slug. Companies are remembered per set of filters. "Company pages or slugs" must be empty. Do not run two schedules with the same filters at the same moment.

## `resetMonitoringState` (type: `boolean`):

Clears everything remembered for this Actor on your account (for every set of filters) before this run reads anything, so this run with monitoring on is a first run again: it remembers the companies listed now and returns nothing. Use it for one run and turn it off again.

## `useProxy` (type: `boolean`):

Requests go directly to www.ycombinator.com, two at a time with a pause between them. If it answers HTTP 403 or 429, the request is sent one more time through an Apify residential proxy, at most three times in a run; if it is refused again the run stops sending requests and says what it did not read. Turn this off to never use a proxy.

## Actor input object example

```json
{
  "companies": [
    "https://www.ycombinator.com/companies/airbnb",
    "stripe",
    "doordash"
  ],
  "allCompanies": false,
  "maxCompanies": 100,
  "maxPagesToRead": 1000,
  "monitoringMode": false,
  "resetMonitoringState": false,
  "useProxy": true
}
```

# Actor output Schema

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

One row per Y Combinator company page: name, slug, batch, status, one-liner, website, team size, year founded, location, country, tags, description, founders (name, title, bio and public LinkedIn / X links as shown on the page), group partner and social links. Slugs with no company page, lines that are not company pages, pages that could not be read, runs with no match or no new company, and runs that hit a limit come back as their own rows and are not charged.

# 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.ycombinator.com/companies/airbnb",
        "stripe",
        "doordash"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/yc-companies-monitor").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.ycombinator.com/companies/airbnb",
        "stripe",
        "doordash",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/yc-companies-monitor").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.ycombinator.com/companies/airbnb",
    "stripe",
    "doordash"
  ]
}' |
apify call neverempty/yc-companies-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/yc-companies-monitor"
        }
    }
}
```

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/KmL80ici7ollFmXYN/builds/neFvPyl9kPLHbAJFK/openapi.json
