Dice Jobs Scraper – Tech Jobs, Search URLs & Companies avatar

Dice Jobs Scraper – Tech Jobs, Search URLs & Companies

Pricing

from $1.20 / 1,000 job results

Go to Apify Store
Dice Jobs Scraper – Tech Jobs, Search URLs & Companies

Dice Jobs Scraper – Tech Jobs, Search URLs & Companies

Pull structured tech job listings from Dice.com by keyword, filters, or Dice URLs. Returns title, company, recruiter type, parsed salary, location, skills, posted date, apply URL/email, and full job description. Auto-paginates with simple pay-per-result pricing and no subscription required.

Pricing

from $1.20 / 1,000 job results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

9 days ago

Last modified

Share

Dice Jobs Scraper

Pull clean, structured tech job listings from Dice (dice.com) at scale. Search by keyword, location, and filters, or paste any Dice search or job URL. Every run returns rich records: title, company, recruiter/employer type, parsed salary, location, workplace type, skills, posted date, apply URL or email, and the full job description. Pay only per result, with no monthly subscription.

Why This Scraper?

  • Dual input: build a search from keywords + location + filters, or paste Dice URLs directly (both search pages and single job pages).
  • Full filter set: posted-date window, employment type, workplace type (remote/hybrid/on-site), employer type (recruiter vs direct hire), Easy Apply, visa-sponsor willingness, and sort by relevance or date.
  • Superset of fields: structured salary (min, max, currency, period), skills list, apply URL and apply email, company profile link, structured street address, and validity dates, on top of every core listing field.
  • Forward pagination: walks result pages automatically until your listing cap or the results run out.
  • Optional detail enrichment: turn on richer per-job data (full description, skills, apply contact) only when you need it.
  • Export anywhere: optionally pipe results into Notion, Linear, Airtable, or any MCP-compatible app.
  • Simple pricing: pay per result, no rental fee, runs on any Apify plan.

Data You Get

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

FieldExample
id00000000000000000000000000000000
guid00000000-0000-0000-0000-000000000000
urlhttps://www.dice.com/job-detail/00000000-0000-0000-0000-000000000000
titleSenior Python Developer
companySample Company
companyLogohttps://d3qscgr6xsioh.cloudfront.net/000000000-logo.webp
companyProfileUrlhttps://www.dice.com/company-profile/00000000-0000-0000-0000-000000000000
cityAustin
stateTexas
countryUSA
locationDisplayAustin, Texas, USA
workplaceTypes["Remote"]
remotetrue
salaryUSD 120,000.00 - 150,000.00 per year
salaryMin120000
salaryMax150000
salaryCurrencyUSD
salaryPeriodyear
employmentTypeFull-time
employerTypeDirect Hire
easyApplyfalse
willingToSponsorfalse
skills["Python", "AWS", "PostgreSQL"]
postedDate2026-01-01T00:00:00Z
applyTypeAPPLY_TO_URL
applyUrlhttps://careers.example.com/apply/0000
applyEmailrecruiter@example.com
summarySample summary text appears here.
descriptionFull HTML description appears here when fetchDetails is on.
companyReviewsnull

Note on reviews: Dice is a job board and does not expose company reviews or star ratings, so companyReviews is always null. Company identity is still captured via company, companyProfileUrl, and companyLogo.

How to Use

Basic keyword search:

{
"mode": "search",
"queries": ["python developer"],
"countryCode": "US",
"maxListings": 50
}

Search with location and filters:

{
"mode": "search",
"queries": ["data engineer"],
"location": "New York, NY, USA",
"radius": 30,
"radiusUnit": "mi",
"employmentType": "FULLTIME",
"workplaceType": "Remote",
"postedDate": "SEVEN",
"sortBy": "date",
"maxListings": 100
}

Multiple keywords with detail enrichment:

{
"mode": "search",
"queries": ["devops", "site reliability engineer"],
"fetchDetails": true,
"maxListings": 200
}

URL mode (paste search or job URLs):

{
"mode": "url",
"urls": [
"https://www.dice.com/jobs?q=golang&countryCode=US",
"https://www.dice.com/job-detail/00000000-0000-0000-0000-000000000000"
],
"maxListings": 100
}

Resume & recurring updates

There are two different things here — pick the one that matches what you're doing:

NeedUse
A crawl stopped and should continueresumeFromRunId / automatic checkpoint recovery
Run the same search every day and receive only changesincrementalMode
Keep separate daily campaigns for similar searchesdistinct stateKey values
Run a normal full snapshotleave both off

Resume (resumeFromRunId) continues one specific interrupted or previous large crawl: paste a run ID or dataset ID and this run skips listings already collected there (deduped on guid), returning only the remaining new listings. An automatic same-run checkpoint also protects against platform migrations/resurrects without any input needed.

Incremental mode (incrementalMode) is for a schedule (for example, daily): the actor remembers the previous run of the same search by itself, so you never paste a run ID. The first run returns everything as NEW. Later runs return only NEW, UPDATED, and REAPPEARED listings by default — duplicates and unchanged listings are suppressed (and not charged, including the detail-enrichment surcharge). Turn on emitUnchanged or emitExpired only when you also want those rows returned (and billed for). State is isolated automatically per mode/keyword/location/filter/URL and fetchDetails setting; set stateKey to name or deliberately share a monitoring campaign. Raising maxPages, maxListings, or maxNotifyListings never starts a new baseline — those are run-size caps, not part of the tracked search.

Scheduled-run example — same search, run daily:

Day 1 (first run ever for this search):

{ "mode": "search", "queries": ["python developer"], "incrementalMode": true }

→ every listing comes back with "changeType": "NEW".

Day 2 (the schedule fires again, identical input):

{ "mode": "search", "queries": ["python developer"], "incrementalMode": true }

→ listings that vanished or reappeared come back as "changeType": "REAPPEARED", listings whose title/salary/company/description/etc. changed come back as "changeType": "UPDATED" with changedFields listing what changed, brand-new postings come back as "changeType": "NEW" — and listings that are still there, unchanged, are not returned at all (suppressed, not charged) unless emitUnchanged is on.

What counts as "changed"

Change detection compares every real listing field. Two fields are deliberately excluded from that comparison because they are not real listing data:

  • scrapedAt — a per-run timestamp, stamped fresh on every push. Comparing it would make every re-scrape look "changed."
  • score — the search relevance score. Measured live (2026-08-04): fetching the same search page twice, 3 seconds apart, changed score on 33 of 33 common listings while every other field (easyApply, modifiedDate, url) stayed byte-identical. It moves with the query and the rest of the index, not with the listing itself, so including it would make emitUnchanged=false runs never suppress anything.

Everything else — title, company, salary/salaryMin/salaryMax, description, skills, employmentType, postedDate, modifiedDate, validThrough, easyApply, and the location fields — is real data and does trigger UPDATED when it changes.

Cap semantics under incremental mode

maxListings (and the per-search share of it) counts listings scanned, not listings emitted. Outside incremental mode the two numbers are always equal, since nothing is suppressed. Under incremental mode with most listings UNCHANGED, counting emitted rows instead would make a quiet run walk deeper and deeper pages to "backfill" the cap with rows it is just going to suppress again — so cost would never drop even when nothing changed. Counting scanned listings means a quiet incremental run costs the same (in pages walked) as the equivalent full run, and stays there.

emitExpired only fires after a complete scan of the tracked search — never on a run capped by maxListings, a resumeFromRunId run, or a run that only fetched individual job detail URLs (those never walk a catalogue page, so there's no way to tell "gone" apart from "not reached"). A partial scan leaves previously-tracked listings' state untouched instead of guessing.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch builds a query from the fields below; url reads the URLs list.
queriesarray["python developer"]Keywords. One scrape per keyword.
locationstring(empty)City + state or country. Empty searches nationwide.
radiusinteger0Distance around the location. 0 uses the site default.
radiusUnitstringmimi or km.
countryCodestringUSTwo-letter country code for the market.
postedDatestringanyany, ONE, THREE, or SEVEN (days).
employmentTypestringanyFULLTIME, PARTTIME, CONTRACTS, THIRD_PARTY.
workplaceTypestringanyRemote, Hybrid, On-Site.
employerTypestringanyRecruiter or Direct Hire.
easyApplybooleanfalseOnly jobs with one-click Easy Apply.
willingToSponsorbooleanfalseOnly jobs whose employer indicates visa-sponsor willingness.
sortBystringrelevancerelevance or date.
urlsarray(example)Dice URLs (URL mode). Filter fields are ignored.
fetchDetailsbooleanfalseAlso fetch each job page for full description, skills, and apply contact.
maxPagesinteger0Safety bound on result pages per search. 0 = unlimited: walk the whole catalogue until a page comes back empty/repeats listings already collected (natural stop), or Max listings is hit first. Set a number only for an explicit page cap below that natural stop.
maxListingsinteger20The sole soft cap on the run, across all searches. Defaults to 20 so a run stays small unless you raise it. 0 = unlimited (bounded only by the natural stop on Max pages).
proxyobjectApify proxyConnection routing. Works on any Apify plan.
mcpConnectorsarray(empty)Optional MCP connectors to also receive results.
resumeFromRunIdstring(empty)Optional prior run ID or dataset ID. Listings already saved by that run are loaded before scraping starts and skipped (deduped on guid), so this run only appends new listings — useful for continuing a large walk-all pull across separate runs. For recurring daily monitoring of the same search, use incrementalMode instead — see "Resume & recurring updates" above.
incrementalModebooleanfalseDaily/recurring monitoring of this same search. First run returns everything as NEW; later runs return only NEW/UPDATED/REAPPEARED by default. See "Resume & recurring updates" above.
stateKeystring(empty)Optional name for a monitoring campaign, so its incremental state stays stable or is deliberately shared. Auto-derived from your search/URL and filter settings when left empty.
emitUnchangedbooleanfalseIncremental mode only. Also return listings unchanged since the last run, marked UNCHANGED. Adds and bills extra rows you already have.
emitExpiredbooleanfalseIncremental mode only. Also return listings from a previous run no longer found, marked EXPIRED, once a run has fully scanned the search (not capped, not a resume, not detail-URLs-only). Adds and bills extra synthetic rows.

Output Example

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

{
"id": "00000000000000000000000000000000",
"guid": "00000000-0000-0000-0000-000000000000",
"url": "https://www.dice.com/job-detail/00000000-0000-0000-0000-000000000000",
"title": "Senior Python Developer",
"company": "Sample Company",
"companyProfileUrl": "https://www.dice.com/company-profile/00000000-0000-0000-0000-000000000000",
"city": "Austin",
"state": "Texas",
"country": "USA",
"locationDisplay": "Austin, Texas, USA",
"workplaceTypes": ["Remote"],
"remote": true,
"salary": "USD 120,000.00 - 150,000.00 per year",
"salaryMin": 120000,
"salaryMax": 150000,
"salaryCurrency": "USD",
"salaryPeriod": "year",
"employmentType": "Full-time",
"employerType": "Direct Hire",
"easyApply": false,
"willingToSponsor": false,
"skills": ["Python", "AWS", "PostgreSQL"],
"positionId": "R000000",
"postedDate": "2026-01-01T00:00:00Z",
"modifiedDate": "2026-01-02T00:00:00Z",
"validThrough": "2026-02-01T00:00:00Z",
"applyType": "APPLY_TO_URL",
"applyUrl": "https://careers.example.com/apply/0000",
"applyEmail": "recruiter@example.com",
"emails": ["recruiter@example.com"],
"summary": "Sample summary text appears here.",
"description": "<p>Full HTML description appears here when fetchDetails is on.</p>",
"companyReviews": null,
"scrapedAt": "2026-01-01T00:00:00.000Z"
}

With incrementalMode on, every record additionally carries changeType (NEW/UPDATED/UNCHANGED/REAPPEARED/EXPIRED), changedFields (array, populated only for UPDATED), firstSeenAt, and lastSeenAt — see "Resume & recurring updates" above.

Send results into your apps (MCP connectors)

Optionally push each result into the tools you already use, through Model Context Protocol (MCP) connectors. Authorize a connector once under Apify, Settings, Integrations, then select it in the mcpConnectors input. For Notion, also set notionParentPageUrl. The connector receives a condensed, human-readable summary per item (title plus key fields); the complete record always stays in the Apify dataset. Leave the field empty to skip. Supported connectors include Notion, Linear, Airtable, and Apify.

Plan Requirement

Runs on any Apify plan, including the free tier. A paid plan with residential routing is optional and can improve reliability for very large runs.