# Built In Jobs Scraper (`automation-lab/builtin-job-listings-scraper`) Actor

Search Built In jobs by keyword, location, employer, category, or URL and export normalized vacancy records with salary, dates, descriptions, and application links.

- **URL**: https://apify.com/automation-lab/builtin-job-listings-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.48 / 1,000 job listing extracteds

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

## Built In Jobs Scraper

Extract **built in jobs** into a clean dataset for recruiting research, hiring-market analysis, and recurring vacancy monitoring. Search Built In by keyword, location, company, category, or a real Built In URL, then receive one normalized record per public job posting.

The Actor follows Built In's server-rendered job search and structured posting data. It returns stable job IDs, titles, employers, locations, salary metadata, dates, full descriptions, and application URLs without requiring a browser or login.

### What can you do with this Built In jobs scraper?

- Search Built In for roles such as `software engineer` or `data engineer`.
- Resolve a city or region through Built In's own public location search.
- Resolve an employer name to Built In's company filter.
- Process a Built In category, filtered search URL, or individual job URL.
- Build scheduled snapshots for vacancy and hiring-market monitoring.
- Export current records to JSON, CSV, Excel, Google Sheets, a database, or another workflow.
- Use stable job IDs and canonical URLs to compare runs in your own pipeline.

This Actor returns current public records. It does not send alerts or maintain a historical database by itself; use an Apify Schedule and compare datasets downstream for those workflows.

### Who is this Actor for?

#### Recruiters and talent teams

Build focused candidate-market and employer-vacancy feeds without manually copying Built In careers pages.

#### Labor-market analysts

Collect consistent job identity, location, employer, salary, and posting-date fields for trend analysis.

#### Sales and lead researchers

Track organizations that are actively hiring for relevant technologies or functions.

#### Data engineers

Feed normalized Built In job records into a warehouse, spreadsheet, webhook, or recurring ETL job.

#### Job-board and career-product teams

Research current public vacancy supply while retaining the canonical source and application links.

### Why use this Actor?

- **Search and source URLs:** start from structured filters or a Built In URL.
- **Full job details:** detail pages provide richer fields than listing cards alone.
- **Typed output:** salary numbers, dates, arrays, nulls, and URLs have predictable types.
- **Location and company resolution:** user-friendly names are translated to Built In's supported search filters.
- **Bounded pagination:** `maxItems` stops discovery and detail fetching at the requested limit.
- **No paid proxy fallback:** the current implementation uses direct public HTTP only.
- **Pay per result:** only validated jobs saved to the dataset trigger the item event.

### What Built In job data is extracted?

| Field | Type | Description |
| --- | --- | --- |
| `jobId` | string | Stable Built In job ID |
| `title` | string | Published job title |
| `company` | string | Hiring employer |
| `companyUrl` | string or null | Employer profile or website URL |
| `location` | string | Readable combined location |
| `locations` | array | Structured city, region, and country values |
| `workplaceType` | string or null | Remote marker when structured data provides it |
| `employmentType` | array | Values such as `FULL_TIME` |
| `salaryMin` | number or null | Published salary minimum |
| `salaryMax` | number or null | Published salary maximum |
| `salaryCurrency` | string or null | Currency code, such as `USD` |
| `salaryPeriod` | string or null | Period, such as `YEAR` or `HOUR` |
| `datePosted` | string or null | Source posting date |
| `validThrough` | string or null | Source expiry timestamp |
| `description` | string or null | Normalized full description when enabled |
| `skills` | array | Structured skills when published |
| `industries` | array | Published industry labels |
| `applyUrl` | string or null | Public direct application URL when available |
| `url` | string | Canonical Built In posting URL |
| `scrapedAt` | string | UTC extraction timestamp |

Source fields that are not published remain `null` or an empty array. The Actor does not infer missing salary, work mode, skills, or expiry values.

### How to scrape Built In jobs

1. Open the Actor in Apify Console.
2. Enter a `query`, such as `software engineer`.
3. Optionally add `location`, `company`, or a Built In `category` slug.
4. Alternatively, paste one or more Built In job or search URLs into `startUrls`.
5. Choose `maxItems` and whether full descriptions should be included.
6. Click **Start**.
7. Open the **Dataset** tab to inspect or export the results.

A useful first run is:

```json
{
  "query": "software engineer",
  "maxItems": 25,
  "includeDescription": true
}
```

### Input parameters

| Input | Type | Default | Meaning |
| --- | --- | --- | --- |
| `startUrls` | array | empty | Built In `/jobs` search/category URLs or `/job/...` detail URLs |
| `query` | string | empty | Title, skill, or keyword search |
| `location` | string | empty | City or region resolved through Built In, for example `New York, NY` |
| `company` | string | empty | Employer resolved through Built In, for example `Smartly` |
| `category` | string | empty | Built In category slug, such as `developer-engineer` |
| `maxItems` | integer | `100` | Maximum records, from 1 to 5,000 |
| `includeDescription` | boolean | `true` | Include normalized full descriptions |
| `maxRequestRetries` | integer | `2` | Retries for temporary network, 429, or server errors |

Provide `startUrls` or at least one search filter. Only `builtin.com` URLs are accepted. Filters supplied alongside a listing URL are applied to that listing search. Filters supplied with an individual job URL are checked against the extracted record.

### Search by location

Use the place a Built In visitor would recognize:

```json
{
  "query": "data engineer",
  "location": "New York, NY",
  "maxItems": 50
}
```

The Actor asks Built In's public location autocomplete for matches and uses the exact text match when available. Otherwise it uses the first result. An unrecognized location fails clearly instead of silently returning an unrelated global search.

### Search by company

```json
{
  "company": "Smartly",
  "maxItems": 25,
  "includeDescription": false
}
```

The Actor prefers an exact employer-name match. When there is no exact result, it uses Built In's first company-search result. Be specific when several employers have similar names.

### Scrape a Built In URL

Use a filtered page or individual posting:

```json
{
  "startUrls": [
    { "url": "https://builtin.com/jobs/remote" }
  ],
  "maxItems": 20,
  "includeDescription": false
}
```

For an individual job URL, the Actor emits at most one record and still applies any provided query, company, or location scope.

### Output example

A current result has this shape:

```json
{
  "jobId": "9354553",
  "title": "C++ Market Data Engineer",
  "company": "Citadel Securities",
  "companyUrl": "https://builtin.com/company/citadel-securities",
  "location": "Miami, Florida, USA / New York, New York, USA",
  "locations": [
    { "city": "Miami", "region": "Florida", "country": "USA" },
    { "city": "New York", "region": "New York", "country": "USA" }
  ],
  "workplaceType": null,
  "employmentType": ["FULL_TIME"],
  "salaryMin": 125000,
  "salaryMax": 350000,
  "salaryCurrency": "USD",
  "salaryPeriod": "YEAR",
  "datePosted": "2026-08-24",
  "validThrough": "2026-09-23T00:18:40+00:00",
  "description": "Job Description About the Role ...",
  "skills": [],
  "industries": ["Information Technology", "Software", "Financial Services"],
  "applyUrl": "https://www.citadelsecurities.com/careers/details/c-market-data-engineer/",
  "url": "https://builtin.com/job/c-market-data-engineer/9354553",
  "scrapedAt": "2026-08-24T06:09:32.620Z"
}
```

The record is illustrative of real current output. Listings change and may omit optional fields.

### How much does it cost to extract Built In job listings?

The Actor uses pay-per-event pricing:

- a **$0.005 start event** once per run;
- an item event for each validated job saved to the dataset;
- no item charge for duplicate, invalid, filtered-out, or failed records.

The BRONZE item price is **$0.0008 per job**, with lower per-item prices on higher Apify tiers. At that tier, 10 jobs cost about **$0.013**, 100 jobs about **$0.085**, and 1,000 jobs about **$0.805**, before any platform-specific taxes or plan effects.

These examples combine the start and item events. Check the pricing panel for the active tier that applies to your Apify account.

### Monitoring new and changed Built In jobs

1. Save a focused Actor input.
2. Create an Apify Schedule for the desired interval.
3. Use `jobId` or `url` as the stable comparison key.
4. Store the previous result set in your own database or key-value record.
5. Compare fields such as `datePosted`, `validThrough`, salary, or description.
6. Send new or changed records through a webhook, Make, Zapier, or another Actor.

Each run is a current snapshot. The Actor does not claim that Built In retains historical versions of a listing.

### Export Built In jobs to a spreadsheet or pipeline

The default dataset can be downloaded as JSON, CSV, Excel, XML, or RSS from Apify Console. For recurring ETL:

- call the Actor through the API;
- wait for the run to finish;
- fetch `defaultDatasetId`;
- request the dataset in the format your destination accepts;
- deduplicate on `jobId` in the destination.

Optional nested arrays are easiest to preserve in JSON. CSV and spreadsheet exports may serialize arrays into cells.

### Run with the Apify API

Replace `APIFY_TOKEN` with your token in a secure environment variable. Do not put tokens in source control.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~builtin-job-listings-scraper/runs?waitForFinish=300" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query":"software engineer","location":"New York, NY","maxItems":25}'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/builtin-job-listings-scraper').call({
  query: 'data engineer',
  location: 'New York, NY',
  maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/builtin-job-listings-scraper').call(run_input={
    'query': 'software engineer',
    'maxItems': 25,
    'includeDescription': True,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/builtin-job-listings-scraper"
```

Use this same JSON configuration in **Claude Desktop**, **Cursor**, or **VS Code**:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/builtin-job-listings-scraper"
    }
  }
}
```

Example prompts:

- “Run the Built In Jobs Scraper for 25 data engineer jobs in New York and summarize the employers.”
- “Extract 20 remote Built In jobs without descriptions and return a CSV-ready table.”
- “Collect current software engineer jobs and group the output by salary currency.”

### Integrations

#### Apify Schedules

Run the same search daily or weekly for consistent hiring snapshots.

#### Webhooks

Notify a service when the run succeeds, then fetch and compare its dataset.

#### Google Sheets

Export a bounded result set for collaborative recruiting or market research.

#### Make and Zapier

Trigger downstream enrichment, routing, or notification workflows after a successful run.

#### Warehouses and databases

Load typed JSON into BigQuery, Snowflake, PostgreSQL, or another analytics store and deduplicate on `jobId`.

### Reliability, retries, and failure behavior

The Actor retries only temporary network failures, rate limits, and selected 5xx responses with bounded backoff. It does not blindly retry malformed inputs, unsupported URLs, or deterministic 4xx responses.

A listing page with no cards ends pagination normally. A detail page that no longer contains a valid JobPosting record is skipped and not charged. If every requested route is invalid or a required filter cannot be resolved, the run fails with a non-zero status.

The source can change its HTML, public endpoints, filters, or structured data. Review failed-run logs before rerunning a large task.

### Tips and limitations

- Start with a small `maxItems` while validating a new search.
- Use specific location text when autocomplete could return several places.
- Use an exact company name when possible.
- Turn off `includeDescription` when descriptions are not needed in downstream output; detail pages are still fetched for normalized metadata.
- Category values are Built In URL slugs, not arbitrary labels.
- Salary and workplace fields are returned only when the source publishes them.
- Built In search ranking can change between runs.
- Direct HTTP is currently sufficient; there is no configurable or automatic residential proxy mode.
- The Actor extracts public listings and does not bypass login, CAPTCHA, or private application systems.

### Responsible and legal use

Use the Actor only for lawful purposes and respect Built In's terms, robots guidance, intellectual-property rights, privacy requirements, and applicable employment-data rules. Public availability does not remove contractual or regulatory obligations.

Avoid republishing full descriptions without permission. Do not use the output for unlawful discrimination, unsolicited spam, or decisions that require protected personal information. Keep request volume proportionate, retain source URLs, and apply appropriate retention and security controls.

You are responsible for deciding whether your use case and jurisdiction permit collection and downstream processing.

### Frequently asked questions

#### Does the Actor require a Built In account?

No. It extracts public job search and detail pages and does not log in.

#### Can it search remote jobs?

Yes. Supply `https://builtin.com/jobs/remote` in `startUrls`, or use another real Built In filtered URL.

#### Can it monitor changes automatically?

Use an Apify Schedule to create recurring snapshots, then compare records by `jobId` in your workflow. The Actor itself does not store historical versions or send alerts.

#### Why is salary null for some jobs?

Built In or the employer did not publish structured salary data for that posting. The Actor does not estimate missing salary.

#### Why did my company or location resolve unexpectedly?

Built In may return several similarly named matches. Use the exact public company name and a specific city/region string. The Actor prefers an exact match and otherwise uses the first Built In result.

#### Why did a run return fewer jobs than `maxItems`?

`maxItems` is a ceiling, not a guarantee. The search can have fewer current listings, duplicate URLs, removed details, or records that do not match filters on a supplied direct job URL.

#### What happens when a job expires during a run?

If the detail no longer exposes a valid JobPosting record, it is skipped and no item event is charged.

### Related automation-lab Actors

- [Company Career Page Jobs Scraper](https://apify.com/automation-lab/company-career-page-jobs-scraper) — normalize jobs from supplied employer career pages.
- [StepStone Jobs & Employer Contacts Scraper](https://apify.com/automation-lab/stepstone-jobs-contact-enrichment) — search StepStone and enrich employer context.
- [iCIMS Jobs Scraper](https://apify.com/automation-lab/icims-jobs-scraper) — collect public jobs from iCIMS-powered career sites.

Use this Actor when Built In is the required source; use the related Actors when you need a different job-board or employer-career-page workflow.

# Actor input Schema

## `startUrls` (type: `array`):

Optional Built In /jobs search URLs or individual /job/... URLs. Query, location, company, and category filters are also applied to supplied URLs.

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

Job title, skill, or keyword, such as software engineer or data scientist.

## `location` (type: `string`):

A city or region recognized by Built In, such as New York, NY. The closest Built In location match is used.

## `company` (type: `string`):

Company name recognized by Built In, such as Google. Exact matches are preferred; otherwise the closest Built In match is used.

## `category` (type: `string`):

Optional Built In job category path slug, for example developer-engineer or data-analytics.

## `maxItems` (type: `integer`):

Maximum number of job records saved to the dataset.

## `includeDescription` (type: `boolean`):

Fetch and return the normalized full job description.

## `maxRequestRetries` (type: `integer`):

Retries for temporary network, rate-limit, and server errors.

## Actor input object example

```json
{
  "startUrls": [],
  "query": "software engineer",
  "maxItems": 20,
  "includeDescription": true,
  "maxRequestRetries": 2
}
```

# Actor output Schema

## `overview` (type: `string`):

Validated job listings saved by this run.

# 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 = {
    "startUrls": [],
    "query": "software engineer",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/builtin-job-listings-scraper").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 = {
    "startUrls": [],
    "query": "software engineer",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/builtin-job-listings-scraper").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 '{
  "startUrls": [],
  "query": "software engineer",
  "maxItems": 20
}' |
apify call automation-lab/builtin-job-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/builtin-job-listings-scraper"
        }
    }
}

```

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/2SATm3nhjZgsj8e07/builds/esdS8yd6ChrNbHu0v/openapi.json
