# CareerBuilder Scraper - Jobs, Salaries & Company Profiles (`abotapi/careerbuilder-scraper`) Actor

Scrape CareerBuilder.com job listings by search or URL. Returns title, company profile, location with coordinates, salary range, employment type, apply link, posting dates, and full job description, with date sorting and optional detail enrichment.

- **URL**: https://apify.com/abotapi/careerbuilder-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 23 total users, 2 monthly users, 78.6% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 job scrapeds

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

## CareerBuilder Scraper: Job Listings, Salaries & Company Profiles

CareerBuilder Scraper turns CareerBuilder job search into a clean dataset. Search by keyword and location, or paste search-result and job-detail links, and get a flat record per job: title, the hiring company's profile, location with map coordinates, salary range, employment type, the apply link, posting dates, and, on request, the complete job description. Run it once, resume an interrupted crawl, or schedule it and get only new and changed jobs on later runs. Export to JSON, CSV or Excel, read the dataset through the API, or pipe results into the apps you already use.

### Why This Scraper?

- **Rich, flat records.** Over 40 possible fields per job, including the hiring company's profile (logo, website, size, description), map coordinates, salary min/max with currency and unit, remote or onsite, and the direct apply link.
- **Two ways to start.** Search by keyword and location, optionally ordered newest first, or paste search-result and job-detail URLs and let the actor walk them.
- **Full descriptions on demand.** Turn on detail enrichment to attach each job's complete description, billed only for jobs actually returned.
- **Multi-search.** Give several keywords and several locations, and every combination is searched.
- **Built for recurring monitoring.** Resume continues one interrupted run without re-collecting or re-billing what it already has. Incremental mode tracks a search across scheduled runs and classifies each job as it changes.
- **Optional export.** Pipe results straight into Notion, Linear, Airtable, or Apify via MCP connectors, right after the dataset is written.

### Use Cases

- **Job boards and aggregators:** compile current CareerBuilder listings by keyword and region for a meta-search product.
- **Recruiting and sourcing teams:** track new postings for competitive intelligence or candidate pipelines by keyword and location.
- **Compensation and salary benchmarking:** collect salary ranges across roles and regions where CareerBuilder publishes them.
- **Labor market research:** schedule incremental runs to track how job counts and postings shift over time for a given search.
- **Employer and company research:** pull the hiring company's profile fields (size, website, description) attached to each posting.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live listing.

| Field | Example |
| --- | --- |
| `jobId` | `00000000-0000-0000-0000-000000000000` |
| `title` | `"Sample Software Engineer"` |
| `company` | `"Sample Company"` |
| `companyLogo` / `companyWebsite` | `"https://media.example.com/logo.png"` / `"http://www.example.com"` |
| `companySize` | `"100 to 499 Employees"` |
| `location` | `"New York, NY, US"` |
| `city` / `state` / `country` | `"New York"` / `"NY"` / `"US"` |
| `latitude` / `longitude` | `40.714` / `-74.006` |
| `isRemote` | `false` |
| `employmentType` | `"Full-time"` |
| `industry` | `"Software"` |
| `salary` | `"USD 160,000 - 185,000 YEAR"` |
| `salaryMin` / `salaryMax` | `160000` / `185000` |
| `salaryCurrency` / `salaryUnit` | `"USD"` / `"YEAR"` |
| `snippet` | `"Short summary of the role."` |
| `skills` | list of skill names the site tags on the job; filled only when detail enrichment is on or for pasted job-detail links, otherwise null |
| `postalCode` | `"02298"`, the job's postal code when the listing gives one |
| `occupationalCategory` | `"15-1132.00: Software Developers, Applications"`, the O\*NET occupation code and title; detail enrichment only, otherwise null |
| `validThrough` | `"2027-10-12T13:31:03.078Z"`, when the posting expires; detail enrichment only, otherwise null |
| `identifier` | the employer's own posting ID; detail enrichment only, otherwise null |
| `description` | full HTML job description (short in search results, full only with detail enrichment on or for pasted job-detail links) |
| `datePosted` / `dateRecency` | `"2026-01-01"` / `"9 days ago"` |
| `applyType` / `applyUrl` | `"INTEGRATED"` / `"https://apply.example.com/job/000"` |
| `directApply` | `true` |
| `url` | `"https://www.careerbuilder.com/job-details/sample--00000000-0000-0000-0000-000000000000"` |

Each record also carries `companyDescription`, `companyFoundingDate` and `companyLocation` (employer profile detail), `jobLocationType` (the raw on-site, remote or hybrid decision behind `isRemote`), `isSalaryExtracted` (whether the salary was stated by the employer rather than estimated), `seoJobId` (used to build the job's detail-page URL), `status`, `jobType` and `promoted` (posting metadata), `provider` (the listing's source name), `formattedDate`, `createdDate` and `modifiedDate` (raw posting timestamps), and `isEligibleForExpertApply`. With Incremental mode on, records also carry `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt`.

### How to Use

1. Pick a **mode**: `search` (keywords, with optional locations) or `url` (paste CareerBuilder search-result or job-detail links).
2. For search mode, fill in **Job keywords** and, optionally, **Locations**, and pick a **Sort by** order. For URL mode, paste one or more links.
3. Turn on **Fetch full job details** if you want the complete description attached (one extra request, and one billed unit, per job actually returned).
4. Set **Max jobs** to control run size and cost, then click **Start**. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search by keyword and location, sorted by date:**

```json
{
  "mode": "search",
  "queries": ["registered nurse"],
  "location": ["Dallas, TX"],
  "sortBy": "date",
  "fetchDetails": true,
  "maxItems": 50
}
```

**Paste links (a search page and a job detail page):**

```json
{
  "mode": "url",
  "startUrls": [
    "https://www.careerbuilder.com/jobs-software-engineer-in-new-york,ny",
    "https://www.careerbuilder.com/job-details/sample--00000000-0000-0000-0000-000000000000"
  ],
  "fetchDetails": true,
  "maxItems": 20
}
```

**Recurring monitoring of one search, only changes returned:**

```json
{
  "mode": "search",
  "queries": ["truck driver"],
  "location": ["Chicago, IL"],
  "incrementalMode": true,
  "stateKey": "chicago-truck-driver-watch",
  "maxItems": 0
}
```

**Continue an interrupted run:**

```json
{
  "mode": "search",
  "queries": ["software engineer"],
  "resumeFromRunId": "<previous run or dataset id>",
  "maxItems": 50
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/careerbuilder-scraper").call(run_input={
    "mode": "search", "queries": ["software engineer"], "location": ["New York, NY"]
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["company"], job["salary"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/careerbuilder-scraper').call({
  mode: 'search', queries: ['software engineer'], location: ['New York, NY'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Resume and recurring updates

Two different features, both optional:

- **Resume** (`resumeFromRunId`) continues one specific interrupted crawl: paste a previous run or dataset ID and the actor skips every job already collected there, so you don't pay twice. No state is kept beyond that one run.
- **Incremental mode** (`incrementalMode`) is for scheduling the same search again and again and getting only what changed. The actor keeps its own baseline for the search, keyed by `stateKey` or an automatic key derived from the search or URLs and the detail setting, and classifies every job as `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED`, `REAPPEARED` or `EXPIRED`. By default only `NEW`, `UPDATED` and `REAPPEARED` jobs return; `UNCHANGED` jobs are suppressed and not billed unless `emitUnchanged` is on. The comparison covers every output field except `dateRecency`, `formattedDate` and `promoted` (they drift or rotate without a real change) and `description`, `skills`, `identifier`, `occupationalCategory` and `validThrough` (only filled when detail enrichment runs or on pasted job-detail links, so they cannot be compared across runs). Excluded fields stay in the output. You can exclude more by listing field names in `ignoreFieldsForChanges` ("Ignore fields when detecting changes (incremental mode only)", in the Resume & recurring updates group); ignored fields never trigger `UPDATED` and never appear in `changedFields`.
- `EXPIRED` is only produced after a run in which every tracked search returned results (the first results page of each search, up to about 50 jobs), with no Max jobs cap hit and no Resume in play, and only when `emitExpired` is on. A job that drops off that first page counts as no longer found. A pasted search URL that starts at `?page=2` or later is a partial scope and never produces `EXPIRED`. `REAPPEARED` can only happen to a job that such a complete scan previously found missing; if `emitExpired` has never been turned on for a search, no job can ever be marked `EXPIRED`, and so `REAPPEARED` never occurs either. Combining Resume with Incremental mode on a search that already has tracked state is rejected: use one or the other, or pick a different `stateKey`.
- Change detection ignores `dateRecency` (a relative label like "9 days ago" that drifts on its own every day), `formattedDate`, `promoted`, and the detail-only fields `description`, `skills`, `identifier`, `occupationalCategory` and `validThrough` (not present on every row, so they can't be compared across runs where the detail setting differs). `datePosted`, salary, snippet and every other field are real data and do trigger `UPDATED`.

#### URL mode

Supported links (all on `https://www.careerbuilder.com`): keyword plus city search (`/jobs-software-engineer-in-new-york,ny`), keyword-only (`/jobs-software-engineer`), state listing (`/jobs-in-ny`), city listing (`/jobs-in-new-york,ny`), remote collection (`/jobs-remote`), industry collection (`/jobs-information-technology-and-internet`), title directory (`/browse/jobs-software-engineer`, accepted but a landing page that may return no jobs), paginated search (`?page=2` starts at that page and never marks earlier jobs expired in Incremental mode), and job details (`/job-details/<slug>--<id>` or `/job-details/<id>`).

Behaviour change: URL mode now has seven sample links as its default, each a different link shape, so switching to URL mode and leaving the field empty runs those samples instead of nothing; clear the field or paste your own links to avoid that.

Links that return no jobs are skipped with a clear warning in the log: other hosts such as `careerbuilder.com` without `www`, the old `/jobs?keywords=` form and `/job/<id>` links. A link that matches nothing, or a job that was removed or expired, also logs a warning and the run still finishes successfully.

#### Output views

The dataset has three table views in the Console: **Jobs Overview** (title, change type, company, location, salary, employment type, remote flag, posting date, apply link, URL), **Job details & company** (description, skills, occupation, expiry, employer posting ID and the employer profile fields) and **Changes (incremental mode)** (change type, changed fields, first and last seen).

### Send results into your apps (MCP connectors)

Optionally pipe every job straight into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable summary of each job, not the full JSON, one entry per job with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

1. Authorize a connector once under **Apify then Settings then Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **mcpConnectors** input field. Notion gets a page per job; Linear, Airtable and Apify get a best-effort write of the same summary.
3. For **Notion**, also set `notionParentPageUrl` to the page under which item pages should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (keywords and optional locations) or `url` (paste links). |
| `queries` | array | none (prefill: `["software engineer"]`) | Job titles or keywords to search (search mode). |
| `location` | array | none (prefill: `["New York, NY"]`) | Optional locations as `City, ST` or a city name; each keyword is searched in each location. Leave empty for nationwide. |
| `startUrls` | array | seven sample links, one per distinct shape (see URL mode) | CareerBuilder search-result, listing, browse or job-detail URLs (url mode). |
| `sortBy` | string | `relevance` | `relevance` (site order) or `date` (reorders the jobs of each fetched page newest first; CareerBuilder offers no server-side sort and its search links ignore filter and sort parameters, so it does not change which jobs are fetched or their order across pages). |
| `keywords` | string | none | Single-keyword alias, added to `queries`. |
| `startUrl` | string | none | Single-link alias, added to `startUrls`. |
| `fetchDetails` | boolean | `false` | Attach the complete job description to each job. |
| `maxItems` | integer | `20` | Total jobs to return across all searches or URLs (`0` = no limit). Each search reads the first results page (up to about 50 jobs) per keyword and location pair. |
| `resumeFromRunId` | string | none | Continue one specific interrupted run, skipping jobs it already collected. |
| `ignoreFieldsForChanges` | array | `[]` | Incremental mode only: output field names excluded from change detection (in addition to `dateRecency`, `formattedDate`, `promoted`, `description`, `skills`, `identifier`, `occupationalCategory`, `validThrough`). |
| `incrementalMode` | boolean | `false` | Recurring monitoring: classify jobs as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED against a stored baseline. |
| `stateKey` | string | none (auto-derived) | Name a monitoring campaign, or leave empty for a key derived automatically from the search and detail settings. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) unchanged jobs, marked UNCHANGED. |
| `emitExpired` | boolean | `false` | Also return (and bill) jobs no longer found, marked EXPIRED. Only produced after a complete, non-resumed, non-capped scan. |
| `proxy` | object | Residential proxy group, country US | Connection settings. |
| `mcpConnectors` | array | none | Optionally send a summary of each job to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | none | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on jobs written to each connector per run. Does not affect the dataset. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live listing.

```json
{
  "mode": "search",
  "jobId": "00000000-0000-0000-0000-000000000000",
  "seoJobId": "sample-software-engineer--00000000-0000-0000-0000-000000000000",
  "title": "Sample Software Engineer",
  "url": "https://www.careerbuilder.com/job-details/sample--00000000-0000-0000-0000-000000000000",
  "status": "ACTIVE",
  "jobType": "FULL_TIME",
  "promoted": false,
  "provider": "CareerBuilder",
  "industry": "Software",
  "company": "Sample Company",
  "companyLogo": "https://media.example.com/logo.png",
  "companyWebsite": "http://www.example.com",
  "companyDescription": "A sample employer description.",
  "companySize": "100 to 499 Employees",
  "companyFoundingDate": "1998",
  "companyLocation": "1 Main St, NY, US",
  "location": "New York, NY, US",
  "city": "New York",
  "state": "NY",
  "country": "US",
  "latitude": 40.714,
  "longitude": -74.006,
  "isRemote": false,
  "jobLocationType": "ON_SITE",
  "employmentType": "Full-time",
  "salary": "USD 160,000 - 185,000 YEAR",
  "salaryMin": 160000,
  "salaryMax": 185000,
  "salaryCurrency": "USD",
  "salaryUnit": "YEAR",
  "isSalaryExtracted": true,
  "snippet": "Short summary of the role.",
  "description": "Full multi-paragraph job description text.",
  "datePosted": "2026-01-01",
  "dateRecency": "9 days ago",
  "formattedDate": "Jan 1, 2026",
  "createdDate": "2026-01-01T00:00:00Z",
  "modifiedDate": "2026-01-01T00:00:00Z",
  "applyType": "INTEGRATED",
  "applyUrl": "https://apply.example.com/job/000",
  "directApply": true,
  "isEligibleForExpertApply": false
}
```

### Plan Requirement

A residential proxy is required. CareerBuilder is protected by an anti-bot interstitial that refuses datacenter traffic, so a run needs a residential connection. The default is the Apify residential proxy group scoped to the United States, which needs a paid Apify plan; Apify free plans do not include residential proxies. On a free plan you can supply your own residential proxy URLs in the **Proxy configuration** field instead. If the residential connection is refused, the run logs this warning once and continues on a backup connection, where some pages may still be unavailable:

```
The selected connection is unavailable to this run.
Apify free plans do not include residential proxies.
Continuing on a backup connection; some pages may still be unavailable.
For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs.
```

When the backup connection serves data, the log says "Served over the backup connection (the default connection was unavailable)."

### FAQ

#### How much does it cost?

You are billed for each job returned, plus a separate detail-enrichment charge for each returned job that carries the full description: jobs enriched with Fetch full job details on, and any job-detail links pasted in URL mode (those always arrive complete). It is charged once per job, immediately after that job is delivered to the dataset (not at the end of the run), only for jobs actually returned, never for jobs suppressed by Incremental mode. The **Pricing** tab shows current rates. Use **Max jobs** to cap the cost of any run.

#### Is it legal to scrape CareerBuilder?

This actor collects only publicly available job-listing data. You are responsible for how you use it: follow CareerBuilder's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution.

#### Can I get only new or changed jobs on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Later runs return only `NEW`, `UPDATED` and `REAPPEARED` jobs by default; unchanged jobs are not billed. `EXPIRED` is opt-in (`emitExpired`) and only appears after a full, uncapped, non-resumed scan, so don't expect it on a first run or a capped run. `REAPPEARED` can only follow such an expiry.

#### What's the difference between Resume and Incremental mode?

**Resume** continues one specific interrupted run from a run or dataset ID, so it never re-collects (or re-bills) what that run already got. **Incremental mode** is for running the same search again and again over time and getting only what changed since last time. Combining both on a search that already has tracked Incremental state is rejected; the run stops with a message asking you to remove one or set a different `stateKey`.

#### Why did my run fail instead of returning an empty dataset?

A run fails outright, with a clear status message, in these cases. (a) No results or job page could be loaded at all (nothing was scanned and every page request was refused or failed). The message depends on what happened: when the proxy connection is refused for the whole account it reads "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid."; on a free plan where residential proxies are unavailable and the backup connection also loaded no page it reads "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested CareerBuilder pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."; for any other case where every page request failed it reads "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later." (b) An invalid `resumeFromRunId` that can't be resolved to a dataset. (c) `resumeFromRunId` combined with `incrementalMode` on a search that already has tracked state. A run finishes as a normal successful run, with an empty or small dataset and a status message explaining why, in these cases: (1) a search or link that matches nothing (the site answered with an empty list or "page not found"): "No jobs matched this search. Check the keywords/location or that the link opens a job list in a browser."; (2) a job link whose posting was removed or expired: it is skipped at once with the log warning "This job is no longer available (removed or expired)" and, if it was the only link, the same "No jobs matched this search." message; (3) every pasted link is an unsupported form: "Every link you pasted is an unsupported form; see the log for the supported link shapes."; (4) no keywords or links were entered: "No search keywords or links were provided, so nothing was searched."; (5) a Resume run where every job scanned was already collected: "No new jobs found: every job scanned was already collected."; (6) an incremental run where nothing changed: "Incremental mode: N job(s) scanned, nothing changed since the last run. Nothing to return.". Run it again in a few minutes if a run failed because nothing could be loaded.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push job summaries into Notion, Linear or Airtable.

### 🔗 Want more jobs data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>💼 <a href="https://apify.com/abotapi/ziprecruiter-com-scraper"><b>ZipRecruiter Scraper</b></a><br>From $1/1K. Scrape ZipRecruiter jobs with titles, companies, salaries, locations...</td><td>💼 <a href="https://apify.com/abotapi/totaljobs-com-scraper"><b>Totaljobs Scraper</b></a><br>Scrape UK job listings from Totaljobs.com by keyword, location, filters, or URL. Extract...</td></tr>
<tr><td>💼 <a href="https://apify.com/abotapi/wellfound-jobs-scraper"><b>Wellfound Jobs Scraper</b></a><br>Scrape startup jobs from Wellfound.com by keyword, location, role, or remote status...</td><td>💼 <a href="https://apify.com/abotapi/remoteok-com-scraper"><b>RemoteOK Jobs Scraper</b></a><br>Scrape RemoteOK jobs by keyword or job URL. Extract title, company, location, remote...</td></tr>
<tr><td>💼 <a href="https://apify.com/abotapi/stepstone-de"><b>StepStone.de</b></a><br>Scrape StepStone.de jobs by keyword, location, filters, or URL. Extract 35+ fields...</td><td>💼 <a href="https://apify.com/abotapi/hiring-cafe-scraper"><b>Hiring.Cafe Jobs</b></a><br>From $1/1K. Unlock powerful Hiring.Cafe job data extraction. Use advanced filters or URLs...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/careerbuilder-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

search = provide job keywords and optional locations. url = paste search-result or job-detail URLs and walk them.

## `queries` (type: `array`):

One or more job titles or keywords, e.g. software engineer, registered nurse, truck driver.

## `keywords` (type: `string`):

Optional single-keyword alias; added to the Job keywords list.

## `location` (type: `array`):

Optional. One or more locations as 'City, ST' (e.g. New York, NY) or a city name. Each keyword is searched in each location. Leave empty for nationwide.

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

Paste CareerBuilder search-result URLs (jobs-...) or job-detail URLs (job-details/...). Multi-URL supported.

## `startUrl` (type: `string`):

Optional single-URL alias; added to the URLs list (URL mode).

## `sortBy` (type: `string`):

Order of results within each search page (newest first when set to date). The site offers no server-side sort, so this re-orders the jobs of each fetched page only; it does not change which jobs are fetched.

## `fetchDetails` (type: `boolean`):

Attach the complete job description to each job. Leave off for description-light results.

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

Total jobs to return across all searches or URLs. This is the run cap (0 means the maximum of 1,000,000).

## `proxy` (type: `object`):

CareerBuilder serves the United States market. Enable the premium connection with country = US for reliable results.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue an interrupted crawl without returning or charging for jobs already collected there. For recurring daily/weekly monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns all matching jobs as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED jobs. A job is UPDATED when any of its output fields changes (title, company, location, salary, snippet, datePosted, apply link, etc.); the changed field names are listed in changedFields. Excluded from the comparison (still present in the output): dateRecency ("3 days ago"), formattedDate and promoted, which drift or rotate without any real change to the job; and description, skills, identifier, occupationalCategory and validThrough, which are only filled when detail enrichment runs or on pasted job-detail links, so they cannot be compared across runs; plus any field you list in "Ignore fields when detecting changes". Turn on "Emit unchanged" or "Emit expired" only when you also want those jobs returned (and billed). State is kept separately for each search/URL and detail-mode setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/URL and detail settings: different searches then never mix state with each other.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return jobs that have not changed since the last run, marked UNCHANGED. This returns and bills extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return jobs that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, not when Max jobs capped it or when Resume was used. This returns and bills extra synthetic rows, so leave it off unless you need expiry tracking.

## `ignoreFieldsForChanges` (type: `array`):

Optional. Output field names (for example salaryMax or companyDescription) to exclude from UPDATED change detection and from changedFields, in addition to the built-in exclusions (dateRecency, formattedDate, promoted, description, skills, identifier, occupationalCategory, validThrough). Excluded fields still appear in the output rows. Use it when a field is noisy for your setup.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify then Settings then API & Integrations, then select it here. Notion gets a page-per-item export; other connectors get a best-effort write. Leave empty to skip. Supported: Notion, Linear, Airtable, Apify.

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which item pages are created. Required only for the Notion export.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "software engineer"
  ],
  "location": [
    "New York, NY"
  ],
  "startUrls": [
    "https://www.careerbuilder.com/jobs-software-engineer-in-new-york,ny",
    "https://www.careerbuilder.com/jobs-software-engineer",
    "https://www.careerbuilder.com/jobs-in-ny",
    "https://www.careerbuilder.com/jobs-in-new-york,ny",
    "https://www.careerbuilder.com/jobs-remote",
    "https://www.careerbuilder.com/jobs-information-technology-and-internet",
    "https://www.careerbuilder.com/job-details/staff-software-engineer-ai-agent-engineering-new-york-ny--31bec029-9bdb-44fa-a006-b8f1b4da5cac"
  ],
  "sortBy": "relevance",
  "fetchDetails": false,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

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

No description

## `detail` (type: `string`):

No description

## `changes` (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 = {
    "mode": "search",
    "queries": [
        "software engineer"
    ],
    "location": [
        "New York, NY"
    ],
    "startUrls": [
        "https://www.careerbuilder.com/jobs-software-engineer-in-new-york,ny",
        "https://www.careerbuilder.com/jobs-software-engineer",
        "https://www.careerbuilder.com/jobs-in-ny",
        "https://www.careerbuilder.com/jobs-in-new-york,ny",
        "https://www.careerbuilder.com/jobs-remote",
        "https://www.careerbuilder.com/jobs-information-technology-and-internet",
        "https://www.careerbuilder.com/job-details/staff-software-engineer-ai-agent-engineering-new-york-ny--31bec029-9bdb-44fa-a006-b8f1b4da5cac"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/careerbuilder-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 = {
    "mode": "search",
    "queries": ["software engineer"],
    "location": ["New York, NY"],
    "startUrls": [
        "https://www.careerbuilder.com/jobs-software-engineer-in-new-york,ny",
        "https://www.careerbuilder.com/jobs-software-engineer",
        "https://www.careerbuilder.com/jobs-in-ny",
        "https://www.careerbuilder.com/jobs-in-new-york,ny",
        "https://www.careerbuilder.com/jobs-remote",
        "https://www.careerbuilder.com/jobs-information-technology-and-internet",
        "https://www.careerbuilder.com/job-details/staff-software-engineer-ai-agent-engineering-new-york-ny--31bec029-9bdb-44fa-a006-b8f1b4da5cac",
    ],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/careerbuilder-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 '{
  "mode": "search",
  "queries": [
    "software engineer"
  ],
  "location": [
    "New York, NY"
  ],
  "startUrls": [
    "https://www.careerbuilder.com/jobs-software-engineer-in-new-york,ny",
    "https://www.careerbuilder.com/jobs-software-engineer",
    "https://www.careerbuilder.com/jobs-in-ny",
    "https://www.careerbuilder.com/jobs-in-new-york,ny",
    "https://www.careerbuilder.com/jobs-remote",
    "https://www.careerbuilder.com/jobs-information-technology-and-internet",
    "https://www.careerbuilder.com/job-details/staff-software-engineer-ai-agent-engineering-new-york-ny--31bec029-9bdb-44fa-a006-b8f1b4da5cac"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/careerbuilder-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/careerbuilder-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/jgae5ItzflMaoejXL/builds/5dIFSJ0gPuM9wlCW2/openapi.json
