AI Job Search & Fit Scorer — 10 Sources + AI Matching avatar

AI Job Search & Fit Scorer — 10 Sources + AI Matching

Pricing

$20.00 / 1,000 retained job fit results

Go to Apify Store
AI Job Search & Fit Scorer — 10 Sources + AI Matching

AI Job Search & Fit Scorer — 10 Sources + AI Matching

Search 10 public developer-job sources or score your own job list against a résumé or profile. Get a ranked shortlist with a 0–100 fit score, a 0–5 delivery score after hard-requirement checks, evidence, skill gaps, and links to the postings. No model key needed.

Pricing

$20.00 / 1,000 retained job fit results

Rating

0.0

(0)

Developer

Job Atlas

Job Atlas

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

21 hours ago

Last modified

Share

Give it one résumé or a short candidate profile. It searches up to 10 public developer-job sources, removes duplicates, reads each full posting, and returns a ranked shortlist with two scores per job: a raw 0–100 fit and a 0–5 delivery score that drops whenever a hard requirement is contradicted. Already have a job list? Skip the search and score your own jobs instead.

No model key is required. Each returned match costs $0.02. In default shortlist mode, jobs that miss the threshold, hard drops, holds, AI failures, and clean empty searches have no result charge. Audit mode charges retained non-failure rows.

Independent, unofficial integration. Not affiliated with or endorsed by LinkedIn or any source-site operator. Review source terms, privacy rules, and applicable law for your use case.

What a result looks like

One real row from a run on 2026-09-05 that scored the built-in example candidate, a generalist senior software engineer:

{
"schemaVersion": "nomad-ai-job-fit-v1",
"jobKey": "linkedin:4436371317",
"title": "Senior Software Engineer, Java",
"company": "CLEAR",
"location": "New York, NY",
"postedAt": "2026-09-05",
"fitScore": 78,
"deliveryScore": 4,
"recommendation": "strong",
"evaluationStatus": "scored",
"blockingGates": [],
"why": "Strong match for a senior full-stack software engineering role: eight years of backend/full-stack experience, React, TypeScript, AWS, Docker, Kubernetes, APIs, and CI/CD align well with the posting.",
"gapSummary": "The posting highlights Java, which is not listed in the candidate’s skills. Work arrangement, New York logistics, and work authorization are not specified.",
"url": "https://www.linkedin.com/jobs/view/senior-software-engineer-java-at-clear-4436371317"
}

How to read it:

  • fitScore (0–100) says how well the posting matches the candidate's skills and target roles.
  • deliveryScore (0–5) is the number to act on. Hard gates such as work mode, location, language, work authorization, seniority, or role family lower it, so a great skills match with an impossible location never reaches the top.
  • blockingGates lists any hard gate that failed. Empty means none did.
  • why and gapSummary are the model's short evidence for and against the match.

The full row also carries the normalized job, every gate verdict, the deterministic pre-screen decision, the model and provider that produced the verdict, source provenance, and stable hashes. The complete example is public: fit-row.example.json.

Run it in one minute

Apify Console. Press Start. The form is prefilled with a bounded search: all ten sources, software-engineer roles posted in the last seven days around Madrid with intern and junior titles excluded, at most three jobs, the example candidate, and a result-charge cap of $0.06. The log, the run status message, and candidate.usedExampleProfile in the run summary all say the results describe that example candidate, not you. Then replace the profile with your own facts, or clear it and upload a résumé. Exactly one candidate source may be set; a run that keeps the profile and adds a résumé is rejected before any paid work starts.

API. This call selects latest, searches one source, and returns at most one match for $0.02:

curl --request POST \
--header "Authorization: Bearer $APIFY_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"mode": "search",
"search": {
"sources": ["linkedin"],
"keywords": ["platform engineer"],
"location": "Madrid",
"postedWithinDays": 7,
"maxItemsPerSource": 1
},
"candidateProfile": {
"primaryRole": "Platform Engineer",
"targetTerms": ["Platform Engineer", "Backend Engineer"],
"skills": ["Python", "PostgreSQL", "Docker"],
"seniorityLevels": ["mid"],
"remoteLocations": ["Spain", "European Union"],
"hybridLocations": ["Madrid, Spain"],
"onsiteLocations": [],
"workArrangementPreferencesComplete": true
},
"maxItems": 1,
"resultMode": "shortlist",
"minDeliveryScore": 2,
"aiConcurrency": 1
}' \
"https://api.apify.com/v2/actors/job-atlas~ai-job-fit-scorer/runs?build=latest&waitForFinish=120&maxItems=1&maxTotalChargeUsd=0.02"

Build 0.1.22 produced the historical example above. Maintained callers select latest and record each returned run’s resolved immutable build ID and numeric build number. Keep the returned run ID, wait for that run to reach SUCCEEDED with exit code 0, then read its default dataset and its RUN-SUMMARY record. Storage counts can settle a moment after the run finishes, so re-read the same run when they have not reconciled yet. A ten-source version of this input is public: search-input.json.

Two ways to use it

Search + score (default)

Set mode to search, give at least one search term, and pick sources. The Actor never invents a query from a résumé, so search.keywords is required. Only the search object narrows what is fetched: put the city or country in search.location, ISO codes for Welcome to the Jungle in search.countryCodes, and remote-only work in search.remoteOnly. A location written in preferences or the candidate profile affects scoring only.

Score jobs you already have

Selecting sourceDatasetId grants this run read-only access to that dataset. For sourceActorRunId outside the Actor's limited access, supply sourceApifyToken with read access to the run and its dataset. The token is an encrypted input; it is never included in results or run summaries. Using the dataset ID avoids needing a separate token.

Set mode to score-jobs, provide one candidate source, and exactly one job source:

  • jobs: inline nomad-agent-job-v1 records (up to 200);
  • sourceDatasetId: an existing Apify dataset, read only;
  • sourceActorRunId: one exact successful upstream Actor run. Add expectedSourceBuild when the upstream build must match.
{
"mode": "score-jobs",
"sourceDatasetId": "YOUR_DATASET_ID",
"candidateProfile": {
"primaryRole": "Data Engineer",
"targetTerms": ["Data Engineer", "Analytics Engineer"],
"skills": ["Python", "SQL", "dbt"],
"remoteLocations": ["European Union"],
"hybridLocations": [],
"onsiteLocations": [],
"workArrangementPreferencesComplete": true
},
"maxItems": 25,
"resultMode": "shortlist",
"minDeliveryScore": 2
}

A complete inline job record is public: inline-input.json.

Candidate input: choose exactly one

  • candidateProfile: structured facts and preferences. Fill only what the candidate actually stated and leave unknowns empty; the scorer treats an empty field as unknown, never as a contradiction.
  • resume: a text-based PDF or TXT uploaded in the Apify Console.
  • resumeText: plain text for API clients.

preferences can add explicit role, location, work-mode, language, or contract constraints for scoring. It does not change which jobs are fetched.

Sources

KeySource
linkedinLinkedIn public job pages
remote_boardsRemote job boards
builtinBuilt In
justjoinitJust Join IT
nofluffjobsNo Fluff Jobs
hackernewsHacker News “Who is Hiring?”
ycombinator_wasY Combinator Work at a Startup
wttjWelcome to the Jungle
infojobsInfoJobs
tecnoempleoTecnoempleo

The default selects all ten listed sources. Results are merged fairly across sources and deduplicated before scoring, and every job needs its full description before it can be scored.

Filter support differs by source. Location is native on LinkedIn, Just Join IT, InfoJobs, and Tecnoempleo. InfoJobs accepts recognized Spanish province names or its own province IDs (for example, Madrid maps to 33); unrecognized locations leave its nationwide search unfiltered. Built In and No Fluff Jobs use developer categories instead of keyword search. A strict remoteOnly search keeps only jobs that are explicitly fully remote, which excludes hybrid and unknown arrangements and therefore most LinkedIn rows. RUN-SUMMARY records, per source, what was fetched and which filters applied.

How scoring works

  1. A deterministic pre-screen reads each posting and sorts it into a hard contradiction (dropped), uncertain evidence (held), or a plausible match (forwarded to AI). minRankToForward sets the forwarding floor and recoverHolds can send holds to AI as well.
  2. Each forwarded job gets one AI verdict: the raw fitScore, a short rationale, gaps, and a pass/fail with evidence for every hard gate.
  3. Any failed hard gate clamps the deliveryScore.
  4. Rows are ordered by delivery score first, then raw fit.

If the model call fails, the row is reported as ai_failed. It is never silently turned into a zero.

Shortlist or audit

resultMode decides what reaches the dataset and what is charged:

  • shortlist (default) returns only rows with evaluationStatus: "scored" and deliveryScore >= minDeliveryScore. The default threshold is 2 and equality counts. Everything else is neither returned nor charged.
  • audit keeps the complete evaluation trail: scored rows, static drops, holds, forward-cap holds, and ai_failed rows. Every retained row except ai_failed is charged. minDeliveryScore is recorded but does not filter.

Output

Dataset rows follow nomad-ai-job-fit-v1 (schema). Three keys matter for automation:

  • matchKey identifies one candidate plus one job. Use it as the upsert key.
  • evaluationKey changes with the exact candidate snapshot, job content, scoring contract, or evaluation time. Keep it as the receipt.
  • jobKey identifies the posting only. Keying a destination on it alone lets one candidate's result overwrite another's.

RUN-SUMMARY in the default key-value store follows nomad-ai-job-fit-run-summary-v4 (schema, real example). It records per-source outcomes, the result policy, warnings, candidate hashes (never résumé text), provider and model usage, billing receipts, and the terminal reason. Its counts block always includes staticDropped, staticHeld, aiScored, aiFailed, resultFilteredOut, and outputRows, so an empty shortlist is distinguishable from a run that did no work. Reconcile the summary with the run and its dataset before writing results anywhere.

Limits

LimitValue
Unique jobs evaluated per run200
AI verdict concurrency1–8
Source concurrency1–10
Résumé upload5 MB, 50 pages, 8,000 readable characters
Job description evidence20,000 characters
Default run timeout15 minutes

Pricing

Result modejob-fit-result is charged whenPrice
shortlist (default)A scored row meets minDeliveryScore and is returned$0.02 per returned match ($20 per 1,000)
auditA complete evaluation row is retained; ai_failed is never charged$0.02 per retained non-failure row ($20 per 1,000)

One charged row is $0.02, 25 are $0.50, 100 are $2.00. There is no search, résumé, run-start, or model-key fee, and no paid child Actor runs: all collectors run inside this Actor.

The model calls are paid by the Actor owner. That route is capped at $0.20/M prompt tokens and $1.20/M completion tokens, with at most two provider attempts per AI call and a fixed $0.25 circuit breaker per run. When the breaker trips, later AI-dependent evaluations become unbilled ai_failed rows in audit mode. Shortlist mode filters those failed rows out.

maxTotalChargeUsd on the run limits how many jobs can be evaluated before their scores are known. A low cap can therefore stop evaluation early even when some later jobs would have been filtered out and left uncharged.

Integrations and agents

The credential-free starters below select latest and verify each resolved immutable run. The accompanying skill, guide, schemas, and examples describe that contract:

The starters are inactive and contain no credentials. Local artifact validation checks the starter configuration. A successful Actor run proves the Actor path; it does not prove your n8n, Make, Zapier, or Google Sheets destination. Test a disposable destination before enabling a schedule.

Caveats

  • Public sites change, rate-limit, block, or omit fields. One source can be partial while the others still return usable rows.
  • A source teaser is not accepted as a full job description. Supplied jobs over the description limit fail validation; searched descriptions may be truncated and are marked when they are.
  • A source that returns zero rows after a verified request is a clean empty result. Unverified empties, all-source failure, or only invalid records fail the run rather than pretending the search was clean.
  • Search responses are cached for cacheTtlSeconds. Set it to 0 when a check must hit the source fresh.
  • Duplicate source identities with conflicting supplied content fail closed.
  • The Actor evaluates one candidate per run and does not learn from clicks or previous runs.
  • Scores are decision support, not facts about a person, and never a substitute for reading the posting.

Privacy and responsible use

  • Only public job pages are in scope. The Actor does not use cookies, borrowed accounts, login or paywall bypasses, or CAPTCHA evasion.
  • Résumés are processed in memory. They are not written as a separate dataset or copied into every fit prompt. The original Actor input or upload remains subject to Apify retention controls.
  • Extracted candidate evidence and fit prompts go through the configured OpenRouter/OpenAI route with provider data collection denied. No zero-data-retention claim is made.
  • File URLs are restricted to Apify upload hosts; arbitrary URL fetching is rejected.
  • Dataset and upstream-run inputs are read only. The Actor never applies to a job, changes source data, or makes an automated hiring decision.

Verify the source posting and keep a human responsible for application and hiring decisions.

Job Atlas

Explore the Job Atlas job-data and matching Actors. Use latest and retain the immutable build ID returned by each run.

Website and integration guides | Source and client examples