# SmartRecruiters Jobs Scraper — Keyword Search, No Company ID (`yugenox/smartrecruiters-jobs-scraper`) Actor

Search live SmartRecruiters jobs by keyword across the employers hiring for it (no company ID needed), or pull every opening from specific companies. Full descriptions, published salaries, apply links, location, remote/hybrid and custom fields. No login.

- **URL**: https://apify.com/yugenox/smartrecruiters-jobs-scraper.md
- **Developed by:** [Yugenox Corp](https://apify.com/yugenox) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 jobs

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

## SmartRecruiters Jobs Scraper

Search **live job postings from employers that hire through SmartRecruiters**. There are two ways to run it:

- **Search by keyword across employers.** Type "data analyst" or "registered nurse" and you get matching jobs from the SmartRecruiters employers hiring for that role right now. You don't need a company ID.
- **Scrape specific companies.** Paste a company ID, its careers link or just its name, and get every open position, optionally filtered by keyword, location, workplace type or date.

Each job comes back as one clean row. It includes the title, company and logo, location with city, region and country, workplace type (on-site, hybrid or remote), employment type, experience level, department, function and industry. It also has the **salary where the employer publishes it**, the full description as HTML, plain text and per-section text, the posting, apply and referral links, the posting date and the employer's custom fields.

No login, cookies or API key are needed.

### What you can do with it

- **Job boards and aggregators**: feed fresh SmartRecruiters postings into your own site, filtered by role, country or remote status.
- **Recruiting and sales intelligence**: find out which companies are hiring for a role, where, and how fast they post.
- **Salary research**: collect published pay ranges by role, city and level.
- **Job alerts**: schedule a daily run with **Only new jobs** turned on, and each run returns only postings you haven't seen yet.
- **Labour-market analytics**: see hiring trends by function, experience level and workplace type.

### How keyword search works

For a keyword search without companies, the scraper works in two steps:

1. It finds the SmartRecruiters employers currently hiring for your keyword, using SmartRecruiters' public job search, and ranks them by how well their jobs match your keyword and location.
2. It collects the matching live postings from the top employers. It works through them best match first, up to **Max companies per keyword** (default 200), and stops once **Max jobs** is reached.

The results come from **those top matching employers**, not from every SmartRecruiters customer. To be sure you get every job at a particular employer, add it under **Companies**.

### Input

| Field | What it does |
|---|---|
| **Search keywords** | Job titles or skills, e.g. `data analyst`. Without companies, this searches across employers. With companies, it filters those companies' jobs. |
| **Companies** | A company ID (`BoschGroup`), a careers link (`https://jobs.smartrecruiters.com/BoschGroup`), a company name (`Northwestern Medicine`) or a single job link. Names are matched to the right company for you. |
| **Country / State / City** | `us`, `United States`, `CA` or `California`, `Chicago`… Case, accents and code-or-name spellings don't matter. |
| **Workplace type** | Any, on-site, hybrid or remote. |
| **Posted within / Posted after** | Only recent jobs: 24h, 3d, 7d, 14d or 30d, or a date. |
| **Keyword match** | *Title* (default): every keyword word is in the job title. *Phrase*: the exact phrase appears anywhere in the ad. *Any*: broadest match. |
| **Employment type / Experience level** | Full-time, part-time, contract, internship… / entry level, associate, mid-senior, director… |
| **Job ad language** | e.g. `en`, `de`, `fr`. |
| **Include full job description** | On by default. Turn it off for faster runs that return listing data only (no description or salary). |
| **Max jobs / Max jobs per company / Max companies per keyword** | Size limits. Use the per-company cap to spread results across employers. |
| **Only new jobs** | Skips jobs this same search already returned on your account. Use it with a schedule. |

Field names are forgiving when you call the API: `keyword`, `query`, `limit`, `maxResults`, `company`, `companyIds`, `startUrls` and a free-text `location` (a country name or a city) are all understood.

#### Example: remote data jobs in the US from the last week

```json
{
  "keywords": ["data analyst", "data engineer"],
  "country": "us",
  "locationType": "REMOTE",
  "postedWithin": "7d",
  "maxItems": 200,
  "maxItemsPerCompany": 20
}
```

#### Example: every open job at two employers in Germany

```json
{
  "companies": ["BoschGroup", "https://jobs.smartrecruiters.com/ServiceNow"],
  "country": "de",
  "maxItems": 1000
}
```

#### Example: daily alert for new nursing jobs in Chicago

```json
{
  "keywords": ["nurse"],
  "country": "us",
  "city": "Chicago",
  "onlyNew": true,
  "postedWithin": "3d"
}
```

### Output

Each job is one row. Here is a trimmed example:

```json
{
  "id": "744000151415579",
  "title": "Data Analyst",
  "company": {
    "identifier": "NBCUniversal3",
    "name": "NBCUniversal",
    "logo": "https://c.smartrecruiters.com/sr-company-logo-prod-aws-dc5/62913a6c84a0d2068a683c44?r=s3-eu-central-1",
    "careersUrl": "https://jobs.smartrecruiters.com/NBCUniversal3"
  },
  "url": "https://jobs.smartrecruiters.com/NBCUniversal3/744000151415579-data-analyst",
  "applyUrl": "https://jobs.smartrecruiters.com/NBCUniversal3/744000151415579-data-analyst?oga=true",
  "releasedDate": "2026-09-23T15:27:28.454Z",
  "postedDaysAgo": 0,
  "location": {
    "city": "New York",
    "region": "NEW YORK",
    "country": "us",
    "countryName": "United States",
    "address": "30 Rockefeller Plaza",
    "postalCode": "10112-0002",
    "fullLocation": "New York, NEW YORK, United States"
  },
  "isRemote": true,
  "isHybrid": false,
  "workplaceType": "remote",
  "employmentType": "Full-time",
  "experienceLevel": "Associate",
  "industry": "Broadcast Media",
  "department": null,
  "function": "Other",
  "language": "en",
  "salary": { "min": 62000, "max": 72000, "currency": "USD", "period": "YEARLY", "source": "posting" },
  "salaryText": "USD 62,000–72,000 / year",
  "customFields": { "Hire Type": "Full-Time Regular", "Business Segment": "NBCUniversal Local" },
  "descriptionHtml": "<h3>Company Description</h3>\n<p>NBCUniversal is one of the world's leading media…",
  "descriptionText": "Company Description\nNBCUniversal is one of the world's leading media and entertainment companies…",
  "sections": {
    "companyDescription": "NBCUniversal is one of the world's leading media…",
    "jobDescription": "The NBCU Digital Media Sales Local Inventory & Analytics team is seeking…",
    "qualifications": "• Bachelor's degree or equivalent experience\n• 2+ years in data analytics…",
    "additionalInformation": "As part of our selection process…"
  },
  "referralUrl": "https://jobs.smartrecruiters.com/external-referrals/company/NBCUniversal3/publication/…",
  "active": true,
  "searchKeyword": "data analyst",
  "source": "keyword",
  "scrapedAt": "2026-09-24T07:31:06.161Z"
}
```

About the salary field:

- `salary.source` is `"posting"` when the employer filled in SmartRecruiters' pay field.
- It is `"description"` when the pay range was read from the job ad text. In that case `salary.text` holds the sentence it came from.
- It is `null` when no pay is published.

Recruiters' names and photos are never included.

### What the run status tells you

Every run finishes with a one-line status, and you are charged only for the jobs saved to the dataset.

- **Done — N jobs …** — everything you asked for, within your limits.
- **Partial — stopped at … : N jobs saved.** — the run hit its time limit, your spending limit, a temporary block or an outage on SmartRecruiters' side, and kept everything collected so far. Run it again to get the rest. When your run's **Timeout** cut it short, the status says so and suggests a longer one.
- **Your run's timeout (N s) ran out before the first job** — the Timeout in the run options was too short to reach the first job. Nothing is charged. A 50-job search usually takes 10–20 s, so 120 s or more is a safe setting. Short timeouts work too: the run stops a few seconds early and keeps what it found.
- **No jobs found — …** — the reason follows: no employer is hiring for that keyword, none matched your location or date filters, the company name or ID is unknown, or SmartRecruiters did not answer. Nothing is charged.
- **Nothing to do — …** — the input needs at least a keyword or a company. Nothing is charged.

A `RUN_REPORT` record in the run's key-value store has the full counts behind the status.

### FAQ

**Do I need a SmartRecruiters account or API key?**
No. The scraper reads public job postings only.

**Is it legal to scrape SmartRecruiters?**
This scraper collects only publicly available data: the job postings employers publish for anyone to read on their SmartRecruiters career pages. It never logs in and never reads anything behind an account. Job ads are business content, and recruiters' names and photos are left out of every row, but an ad's own text can occasionally name a contact person or give a contact email. If you store or reuse personal details like that, data-protection laws such as GDPR (EU), PIPEDA (Canada) and CCPA (California) apply, so use the data in line with those laws and SmartRecruiters' terms. If you are unsure about your use case, check with a lawyer. More background: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

**Does it access any private data?**
No. It reads only the live, public job postings that anyone can open on jobs.smartrecruiters.com or on an employer's careers site, with no login, cookie or API key. It never touches candidate profiles, applications, internal notes or anything else inside an employer's SmartRecruiters account, and it drops the recruiter's name and photo that come attached to each posting.

**How do I find a company's ID?**
It's the part after `jobs.smartrecruiters.com/` in the company's job links, e.g. `BoschGroup`. You can also type the company name. If several companies share a name, the run log lists the alternatives it didn't pick.

**A company returned nothing. Why?**
Either the company doesn't use SmartRecruiters, it has no open jobs right now, or the ID is misspelled. The run log and status message tell you which companies were skipped.

**Why do I get fewer jobs than the employer shows on its careers site?**
Your filters apply, including **Keyword match = Title**, which is strict on purpose. Switch it to *Phrase* or *Any* for broader results. Some employers also list jobs from other hiring systems on their own site.

**Is the salary always available?**
No, only when the employer publishes it. Pay ranges are common in US states with pay-transparency laws and in parts of Europe.

**How fresh is the data?**
It is fetched live when the run starts. With **Only new jobs** turned on, schedule it hourly or daily for alerts.

**Can I get only listing data, without descriptions?**
Yes. Turn off **Include full job description**. Those runs are faster and lighter.

# Actor input Schema

## `keywords` (type: `array`):

Job titles or skills to search for, e.g. "data analyst" or "nurse". Without companies, the scraper finds the SmartRecruiters employers currently hiring for each keyword and collects their matching jobs. With companies, keywords filter those companies' jobs.

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

Employers to scrape: the company ID (e.g. "BoschGroup"), its careers link (jobs.smartrecruiters.com/BoschGroup or careers.smartrecruiters.com/BoschGroup), a company name (e.g. "Northwestern Medicine") or a link to a single job posting. Leave empty to search across all SmartRecruiters employers by keyword.

## `country` (type: `string`):

Two-letter country code ("us", "ca", "gb", "de", "in"…) or a country name.

## `region` (type: `string`):

Code or name, e.g. "CA" or "California", "ON" or "Ontario". Matches every spelling employers use.

## `city` (type: `string`):

e.g. "Chicago", "Toronto", "Bengaluru". Case and accents don't matter.

## `locationType` (type: `string`):

On-site, hybrid or remote jobs only.

## `postedWithin` (type: `string`):

Only jobs published in this period. Handy for daily or weekly scheduled runs.

## `postedAfter` (type: `string`):

Only jobs published after this date, e.g. 2026-09-01.

## `keywordMatch` (type: `string`):

Title: every keyword word appears in the job title (most precise). Phrase: the exact phrase appears anywhere in the job ad. Any: SmartRecruiters' own broad full-text match (most results, least precise).

## `employmentTypes` (type: `array`):

Keep only these employment types. Empty = all.

## `experienceLevels` (type: `array`):

Keep only these experience levels. Empty = all.

## `language` (type: `string`):

Two-letter language code of the job ad, e.g. "en", "de", "fr".

## `includeDetails` (type: `boolean`):

Adds the full description (HTML + plain text, split into sections), salary where published, referral link and active status. Turn off for faster, lighter runs with listing data only.

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

Stop after this many jobs in total. 0 = no limit.

## `maxItemsPerCompany` (type: `integer`):

Cap per employer, so one big employer doesn't fill the whole run. Empty = no cap.

## `maxCompaniesPerKeyword` (type: `integer`):

For keyword searches without companies: at most this many of the best-matching employers are searched, best first. The run stops earlier once Max jobs is reached.

## `onlyNew` (type: `boolean`):

Skip jobs this same search already returned in earlier runs on your account. Schedule the actor daily to get just the new postings.

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

Parallel requests. 15 is fast and gentle; up to 30 for big runs.

## `proxyConfiguration` (type: `object`):

Apify datacenter proxy works well (default).

## Actor input object example

```json
{
  "keywords": [
    "data analyst"
  ],
  "country": "us",
  "locationType": "any",
  "postedWithin": "any",
  "keywordMatch": "title",
  "includeDetails": true,
  "maxItems": 50,
  "maxCompaniesPerKeyword": 200,
  "onlyNew": false,
  "concurrency": 15,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All scraped job postings.

## `run` (type: `string`):

Status and statistics for 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 = {
    "keywords": [
        "data analyst"
    ],
    "country": "us",
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("yugenox/smartrecruiters-jobs-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 = {
    "keywords": ["data analyst"],
    "country": "us",
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("yugenox/smartrecruiters-jobs-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 '{
  "keywords": [
    "data analyst"
  ],
  "country": "us",
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call yugenox/smartrecruiters-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yugenox/smartrecruiters-jobs-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/V8bVvpIOiWJyJbZ4K/builds/S2Nwtb5sVz4PyfRnq/openapi.json
