Company Jobs Tracker
Pricing
from $50.00 / 1,000 company trackeds
Company Jobs Tracker
Track job listings for specific companies across StepStone portals (DE, AT, BE, NL, Totaljobs, NIjobs, Pnet). Detects new, changed, and removed postings with stateful diff tracking. Pay per company tracked.
Pricing
from $50.00 / 1,000 company trackeds
Rating
0.0
(0)
Developer
Black Falcon Data
Actor stats
1
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share

Company Jobs Tracker — Hiring Monitor for 18 StepStone Group Portals
What is Company Jobs Tracker?
Company Jobs Tracker is an Apify Actor that monitors company hiring activity across 18 European job portals in the StepStone Group network. Input a list of companies, and receive structured change detection output on each run: which new jobs appeared, which removed jobs disappeared, and how many remain unchanged.
Built for recruitment pipelines, sales intelligence workflows, and investor due diligence. One record per company per run — predictable, pipeline-ready output. Schedule daily for continuous hiring signal without manual effort.
Key features
🏢 Company-level change detection
- Track any combination of companies across StepStone's 18-portal network
- New jobs, removed jobs, and unchanged counts per company per run
- One structured record per company — stable output for downstream pipelines
🎯 Exact company targeting
- Use
companyIdfor server-side filtering — the portal returns only that company's listings, no client-side guesswork - Discover
companyIdautomatically from any calibration run - Eliminates false positives from subsidiary names and ambiguous employer listings
🔄 Incremental change detection
- First run establishes a baseline; subsequent runs return only what changed
- Two-run removal confirmation prevents transient SERP fluctuations from triggering false removals
- State persists across scheduled runs automatically
⚙️ Calibration mode
- Run with
calibrateOnly: truebefore committing to a tracking schedule - Identifies company name mismatches and shows the actual employer names returned by the portal
- Writes no state — safe to run as many times as needed
📦 Predictable output
- Always one record per input company, even on error or portal block
- Unchanged jobs appear as a count only — no dataset bloat
- Suitable for Google Sheets, webhooks, and ETL pipelines
💰 Predictable pricing
- Flat $0.05 per company per run
- Built-in cost guards prevent unexpected overruns
How it works
On the first run, the actor scrapes each company's job listings and stores them as a baseline. All jobs are classified as new, and no removals are reported — this is expected.
On each subsequent run, the actor re-scrapes and compares against the stored baseline:
- Jobs found now but not before → new
- Jobs found before but not now → candidates for removal (see Removal confirmation)
- Jobs found in both runs → unchanged (counted, not listed)
The actor writes one dataset record per company per run regardless of outcome. Failed scrapes preserve the existing baseline — no false removals.
Recommended onboarding flow
Run calibrateOnly: true before enabling live tracking. This validates your company name setup without writing any state.
Step 1 — Calibration run
{"companies": [{ "name": "Siemens", "geo": "DE" },{ "name": "Bosch", "geo": "DE" }],"calibrateOnly": true}
Step 2 — Check warnings
Look at the warnings field in each output record. A warning like:
no_company_match: 0/50 jobs matched "Bosch" in strict_normalized mode.Top company names in results: "Robert Bosch GmbH", "Bosch Rexroth AG", "Bosch Sicherheitssysteme GmbH".
means the search returns results, but none match "Bosch" under strict_normalized. The portal lists the company as "Robert Bosch GmbH".
Step 3 — Adjust
Either:
- Change
nameto"Robert Bosch GmbH"so normalisation strips "GmbH" and matches correctly, or - Switch to
"matchMode": "prefix"so "Bosch" matches anything starting with "Bosch", or - Use
companyIdfor exact server-side filtering (most reliable — see How to find companyId)
Step 4 — Enable live tracking
Once warnings are clear, remove calibrateOnly and schedule the run.
Quick start
Minimal input — three companies across DE, UK, and South Africa:
{"companies": [{ "name": "SAP", "geo": "DE" },{ "name": "Unilever", "geo": "TOTALJOBS" },{ "name": "Sasol", "geo": "PNET" }],"maxResultsPerCompany": 50}
For exact matching, add companyId — see How to find companyId below.
Schedule this run daily to receive a structured diff of hiring activity for each company.
Input parameters
Top-level fields
| Parameter | Type | Default | Description |
|---|---|---|---|
companies | array | — | List of companies to track — required |
includeDetails | boolean | false | Fetch full job descriptions — slower and more expensive |
maxResultsPerCompany | number | 50 | Max jobs fetched per company per run (max: 100) |
calibrateOnly | boolean | false | Dry-run mode — no state written, no removals emitted |
removedConfirmationRuns | number | 1 | Consecutive missed runs before a job is confirmed removed |
maxCompanies | number | 200 | Hard cap on companies processed per run |
maxTotalRequests | number | 500 | Hard cap on total HTTP requests — excess companies are skipped |
proxyConfiguration | object | Apify proxy | Proxy settings — residential proxy required for some portals |
Per-company fields (companies[])
| Field | Type | Default | Description |
|---|---|---|---|
name | string | — | Company display name — used in output and matching (required) |
geo | string | — | Portal to search — DE, AT, NL, BE, TOTALJOBS, CWJOBS, … (required) |
query | string | = name | Search query override — useful when the company name is not a good search term |
companyId | number | null | Server-side filter — bypasses client-side matching entirely when set |
matchMode | select | strict_normalized | strict / strict_normalized / prefix / contains |
Examples
Track two companies
{"companies": [{ "name": "Siemens", "geo": "DE" },{ "name": "SAP", "geo": "DE" }],"maxResultsPerCompany": 20}
Calibrate before tracking
{"companies": [{ "name": "BMW", "geo": "DE" }],"calibrateOnly": true}
Exact match with companyId
{"companies": [{ "name": "SAP", "geo": "DE", "companyId": 215050 }],"maxResultsPerCompany": 50}
Example output
{"company": "Siemens","geo": "DE","scrapeOutcome": "success","counts": { "new": 3, "removed": 1, "unchanged": 42, "total": 45 },"isFirstRun": false}
Output
The actor emits one record per company per run. Unchanged jobs are counted but not listed individually.
Sample output
{"company": "SAP","geo": "DE","matchMode": "strict_normalized","scrapeOutcome": "success","runAt": "2026-03-11T06:00:00.000Z","previousRunAt": "2026-03-10T06:00:00.000Z","isFirstRun": false,"counts": { "new": 3, "removed": 1, "unchanged": 42, "total": 45 },"serpCount": 120,"processedCount": 50,"matchedCount": 45,"anonymousSkippedCount": 0,"costGuardTriggered": false,"warnings": [],"error": null,"newJobs": [{"trackId": "job-abc123","title": "Senior Java Developer","company": "SAP SE","url": "https://www.stepstone.de/stellenangebote--Senior-Java-Developer-..."}],"removedJobs": [{"trackId": "job-xyz789","title": "Data Analyst","company": "SAP SE","url": "https://www.stepstone.de/...","firstSeen": "2026-03-05T06:00:00.000Z","lastSeen": "2026-03-09T06:00:00.000Z","removedAt": "2026-03-11T06:00:00.000Z"}]}
Example output record
{"company": "SAP","geo": "DE","matchMode": "strict_normalized","scrapeOutcome": "success","runAt": "2026-03-11T06:00:00.000Z","previousRunAt": "2026-03-10T06:00:00.000Z","isFirstRun": false,"counts": {"new": 3,"removed": 1,"unchanged": 42,"total": 45},"serpCount": 120,"processedCount": 50,"matchedCount": 45,"anonymousSkippedCount": 0,"costGuardTriggered": false,"warnings": [],"error": null,"newJobs": [{"trackId": "job-abc123","title": "Senior Java Developer","company": "SAP SE","url": "https://www.stepstone.de/stellenangebote--Senior-Java-Developer-..."}],"removedJobs": [{"trackId": "job-xyz789","title": "Data Analyst","company": "SAP SE","url": "https://www.stepstone.de/...","firstSeen": "2026-03-05T06:00:00.000Z","lastSeen": "2026-03-09T06:00:00.000Z","removedAt": "2026-03-11T06:00:00.000Z"}]}
Output fields
| Field | Type | Description |
|---|---|---|
company | string | Company name from input |
geo | string | Portal code |
matchMode | string | Matching mode used |
scrapeOutcome | string | Result of the scrape: success, empty_serp, empty_after_filter, blocked, blocked_suspected, error, skipped |
runAt | string (ISO) | Current run timestamp |
previousRunAt | string (ISO) | null | Previous successful run timestamp |
isFirstRun | boolean | True when no prior state exists for this company |
counts.new | number | Jobs new since last run |
counts.removed | number | Jobs confirmed removed |
counts.unchanged | number | Jobs present in both runs |
counts.total | number | Total matched jobs in current run |
serpCount | number | Total results returned by portal |
processedCount | number | Jobs actually fetched (up to maxResultsPerCompany cap) |
matchedCount | number | Jobs that passed company matching |
anonymousSkippedCount | number | Listings with no employer name — skipped from matching |
costGuardTriggered | boolean | True if this company was skipped due to request cap |
warnings | string[] | Calibration hints — includes top employer names when 0 jobs match |
error | string | null | Error detail when scrapeOutcome is error |
newJobs | array | Full details of new jobs — trackId, title, company, url |
removedJobs | array | Details of confirmed removed jobs — includes firstSeen, lastSeen, removedAt |
Unchanged jobs are not listed individually — only counted. This keeps dataset size predictable across runs.
Company matching
When companyId is not set, the actor filters SERP results by employer name. The matchMode controls how strictly names are compared.
| Mode | Behavior |
|---|---|
strict_normalized | Lowercases, strips punctuation, removes legal suffixes (AG, GmbH, Ltd, …), then requires exact equality. Default. |
strict | Case-insensitive trimmed equality — no suffix stripping |
prefix | Normalized listing name starts with normalized input name |
contains | Normalized listing name contains normalized input name |
Example: "Bosch" in strict_normalized mode will not match "Bosch Gruppe GmbH" because normalisation produces "bosch gruppe" ≠ "bosch". Use prefix mode, or provide companyId for a guaranteed match.
Legal suffixes stripped by strict_normalized include: AG, GmbH, GmbH & Co. KG, KG, SE, Ltd, Limited, Inc, LLC, PLC, A/S, ApS, AB, BV, NV, SA, SARL, and more.
When 0 results match in strict or strict_normalized mode, the actor emits a warning listing the top employer names from that search — use this to calibrate your input name.
How to find companyId
Using companyId is the most reliable way to track a company. The portal applies the filter server-side, so all returned results belong to that company and no client-side matching is needed.
To find a company's ID, open any job listing from that company on the relevant StepStone Group portal (e.g. stepstone.de, totaljobs.com). The companyId appears as a numeric parameter in the listing URL or in the page source. Copy it into companies[].companyId in your input.
Once companyId is set, matchMode is ignored for that company entry.
Removal confirmation
A job is only marked removed after it is absent from two consecutive successful scrapes (default). This prevents transient SERP ranking changes or one-off portal variations from triggering false removal alerts.
The removedConfirmationRuns input controls this threshold:
| Value | Behavior |
|---|---|
1 (default) | Job must be missing in 2 consecutive successful runs before confirmed removed |
0 | Aggressive mode — job confirmed removed after a single missed run (more noise) |
2 | Job must be missing in 3 consecutive runs — more conservative, fewer false positives |
Failed scrapes (blocked, error) do not advance the removal countdown — only successful scrapes count.
Supported portals
This actor tracks companies across 18 portals in the StepStone Group network — the same portals covered by the StepStone Jobs Feed actor. Use the geo field per company entry to select the portal.
| Region | Portal | geo value | Proxy |
|---|---|---|---|
| 🇩🇪 Germany | stepstone.de | DE | None |
| 🇦🇹 Austria | stepstone.at | AT | None |
| 🇧🇪 Belgium | stepstone.be | BE | None |
| 🇳🇱 Netherlands | stepstone.nl | NL | None |
| 🇬🇧 United Kingdom | totaljobs.com | TOTALJOBS | Required |
| 🇬🇧 United Kingdom | cwjobs.co.uk | CWJOBS | None |
| 🇬🇧 United Kingdom | jobsite.co.uk | JOBSITE | None |
| 🇬🇧 United Kingdom | milkround.com | MILKROUND | None |
| 🇬🇧 United Kingdom | caterer.com | CATERER | None |
| 🇬🇧 United Kingdom | retailchoice.com | RETAILCHOICE | Required |
| 🇬🇧 United Kingdom | careerstructure.com | CAREERSTRUCTURE | None |
| 🇬🇧 United Kingdom | cityjobs.com | CITYJOBS | None |
| 🇬🇧 United Kingdom | justengineers.net | JUSTENGINEERS | None |
| 🇬🇧 United Kingdom | emedcareers.com | EMEDCAREERS | Required |
| 🌐 International | catererglobal.com | CATERERGLOBAL | None |
| 🇮🇪 Ireland | nijobs.com | NIJOBS | None |
| 🇮🇪 Ireland | jobs.ie | JOBSIE | None |
| 🇿🇦 South Africa | pnet.co.za | PNET | None |
Portals marked Required need a residential proxy — pass proxyConfiguration with the RESIDENTIAL group.
Note: Some portals require browser automation (Playwright), which increases compute cost per run (e.g., BE, NL, EMEDCAREERS).
Pricing
$0.05 per company per run. Charged as a PAY_PER_EVENT fee — one event per company entry processed.
Platform compute costs (CU) are charged separately by Apify based on your subscription plan. A typical run tracking 10 companies on Cheerio portals (DE, AT, UK) costs less than $0.01 in compute. Playwright portals (BE, NL, EMEDCAREERS) cost more per request.
Example costs (event fees only)
| Companies | Frequency | Monthly event cost |
|---|---|---|
| 10 | Daily | $15 |
| 50 | Daily | $75 |
| 200 | Daily | $300 |
Compute costs are typically negligible compared to event fees. Built-in caps (maxCompanies, maxTotalRequests) prevent unexpected overruns — companies that cannot be processed within the caps are skipped and flagged in output with costGuardTriggered: true.
Use cases
Recruitment Monitor target accounts and client companies for new job openings. Know the moment a company starts hiring for a specific role — before your competitors notice.
Sales intelligence Use hiring activity as a buying signal. Companies posting large volumes of new roles in engineering or operations are often investing in new tooling or scaling rapidly.
Investor due diligence Track portfolio company hiring velocity over time. Cross-reference hiring acceleration or deceleration against financial reports and market signals.
Competitor intelligence Monitor what roles your competitors are hiring for, in which locations, and at what volume. Detect strategic pivots early from changes in job mix.
Market research Track hiring trends across an industry sector by monitoring multiple companies simultaneously. Quantify labour demand shifts by role, region, and company size.
Known limitations
- First run is always a baseline — all jobs appear as new, no removals are reported. Tracking becomes meaningful from the second run onwards.
- SERP ranking changes between runs can cause the same job to appear or disappear from the fetched page window without actually being posted or removed. The default
removedConfirmationRuns: 1reduces noise from this. strict_normalizedmatching may not capture subsidiaries or brands with distinct legal names (e.g. "Bosch Rexroth AG" vs "Bosch"). UsecompanyIdorprefixmode for these cases.- Portals marked Required (
totaljobs.com,retailchoice.com,emedcareers.com) incur additional residential proxy costs. - Playwright portals (BE, NL, EMEDCAREERS) cost more per request than Cheerio portals.
irishjobs.ieis not supported — the portal uses anti-scraping protections that block automated access.- Some portals may temporarily return errors due to transient network conditions. Rerunning usually resolves this.
Support
This actor is self-serve. Follow the onboarding flow above to validate your setup before enabling live tracking.
If you run into an issue, use the Issues tab on this actor's Apify page and include your run ID and input configuration.