Scrape Dice Jobs for US Tech Recruiting Data (2026 Guide)
Pull US tech jobs from Dice.com with Thirdwatch's Dice Jobs Scraper — title, company, location, salary, remote flag, summary, optional skills. Python recipes.

Thirdwatch's Dice Jobs Scraper turns Dice.com search results into clean dataset rows —
title,companyName,locationDisplay,salary,employmentType,isRemote,summary,postedDate, anddetailsPageUrl, with an optional per-jobskillslist. No login, no API key. Built for US tech recruiters, sourcers, compensation analysts, and hiring-market intelligence teams who need structured Dice data programmatically.
Why scrape Dice for US tech recruiting
Dice is one of the oldest and most tech-concentrated job boards in the US, and that concentration is exactly what makes it valuable for sourcing. Dice's 2024 Tech Salary Report put the average US technologist salary at roughly $111,000, with the platform indexing hundreds of thousands of active technology roles at any given time. Unlike a general board where tech postings are diluted by every other vertical, almost everything on Dice is a software, data, cloud, security, or IT role — so a single keyword query returns a high-signal slice of the US tech-hiring market.
The job-to-be-done is structured. A staffing agency placing contract DevOps engineers wants the current open python and kubernetes roles in three metros, refreshed daily, deduped against last week's pull. An in-house TA team tracks which competitors are hiring senior backend engineers and at what posted bands. A compensation analyst builds a title × location salary distribution to sanity-check an offer. A market-intel team watches the velocity of data engineer postings as a demand signal. All of these reduce to keyword-plus-location pulls returning structured rows — which is exactly what the actor produces.
How does this compare to the alternatives?
Three options for getting Dice jobs data into a pipeline:
| Approach | Cost | Reliability | Setup time | Maintenance |
|---|---|---|---|---|
| DIY Python scraper | Free compute, weeks of dev | Brittle when Dice changes its markup | 2–4 weeks | You own the parser and anti-bot work |
| Generic scraping API | Subscription required | Generic — no Dice-specific fields | Days | You still build the Dice parser on top |
| Thirdwatch Dice Jobs Scraper | Transparent pay-per-result | Production-tested on Dice search | 5 minutes | Thirdwatch tracks Dice changes |
A DIY scraper looks cheap until Dice reshapes its search response and your salary and jobLocation parsing silently breaks. A generic scraping API hands you raw HTML and leaves the Dice-specific extraction to you. The Dice Jobs Scraper actor page returns the parsed fields — company, structured location, salary text, remote flag, summary, apply URL — out of the box, so the data lands recruiter-ready.
How to scrape Dice jobs for US tech recruiting in 4 steps
Step 1: How do I authenticate against Apify?
Sign in at apify.com (free tier, no credit card), open Settings → Integrations, and copy your personal API token. Every example below assumes the token is in APIFY_TOKEN:
export APIFY_TOKEN="apify_api_xxxxxxxxxxxxxxxx"Step 2: How do I pull tech jobs by keyword and location?
Pass your keyword in q, narrow with location, and cap the run with maxResults. The defaults search python across the whole US.
import os, requests, pandas as pd
ACTOR = "thirdwatch~dice-jobs-scraper"
TOKEN = os.environ["APIFY_TOKEN"]
resp = requests.post(
f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items",
params={"token": TOKEN},
json={
"q": "data engineer",
"location": "Austin, TX",
"maxResults": 100,
},
timeout=900,
)
df = pd.DataFrame(resp.json())
print(f"{len(df)} jobs across {df.companyName.nunique()} employers")A single 100-result pull is small enough to run on demand. For a multi-role sweep, loop several q values (e.g. python, devops, data engineer) and concatenate the frames before deduping on detailsPageUrl.
Step 3: How do I filter for remote roles and published salaries?
isRemote is a clean boolean from Dice's own classification — far more reliable than grepping "remote" out of titles. Salary is text and may be absent or "Depends on Experience", so filter before you parse.
# Remote-only view
remote = df[df.isRemote == True].copy()
# Rows with a real numeric salary band (drop nulls and "Depends on Experience")
has_band = df.salary.fillna("").str.contains(r"\d{2,3}[,.]?\d{3}", regex=True)
paid = df[has_band].copy()
print(remote[["title", "companyName", "locationDisplay", "salary",
"employmentType", "detailsPageUrl"]].head(10))
print(f"{len(paid)} of {len(df)} listings published a numeric salary band")employmentType (Full-time, Contract, etc.) and workplaceTypes (On-Site, Remote, Hybrid) let you split contract from full-time and on-site from hybrid without touching the description text.
Step 4: How do I add the required-skills list per job?
The base listing does not include skills. Enable the scrapeSkills toggle to fetch each job's detail page and populate the skills array. This makes one extra request per job, so it is slower — use it on focused, smaller runs.
resp = requests.post(
f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items",
params={"token": TOKEN},
json={
"q": "devops",
"location": "Remote",
"maxResults": 25,
"scrapeSkills": True,
},
timeout=900,
)
df = pd.DataFrame(resp.json())
# Count the most in-demand skills across the cohort
from collections import Counter
skills = Counter(
s.lower() for row in df.skills.dropna() if isinstance(row, list) for s in row
)
print(skills.most_common(15))For a recurring pipeline, wrap this in an Apify schedule and add an ACTOR.RUN.SUCCEEDED webhook that upserts new rows into your ATS or CRM, keyed on detailsPageUrl.
Sample output
Each dataset row mirrors a Dice listing. Below are two records — one full-time on-site role with a published band, one remote contract role where Dice returned "Depends on Experience". Five rows of this shape weigh roughly 12 KB.
[
{
"title": "Senior Lead Software Engineer, Full Stack (Python, ReactJS, AWS)",
"companyName": "Capital One",
"jobLocation": {
"city": "New York",
"state": "NY",
"country": "USA",
"displayName": "New York, New York, USA"
},
"locationDisplay": "New York, New York, USA",
"salary": "USD 229,900.00 - 262,400.00 per year",
"employmentType": "Full-time",
"workplaceTypes": ["On-Site"],
"isRemote": false,
"easyApply": false,
"summary": "We are looking for a Senior Lead Software Engineer to build customer-facing platforms across Python, ReactJS, and AWS...",
"postedDate": "2026-06-18T21:19:30Z",
"detailsPageUrl": "https://www.dice.com/job-detail/b3df44c4-d9d3-4ec0-bf46-7393cd4a5ef7"
},
{
"title": "DevOps Engineer (Kubernetes, Terraform)",
"companyName": "TechStaff Solutions",
"locationDisplay": "Remote",
"salary": "Depends on Experience",
"employmentType": "Contract",
"workplaceTypes": ["Remote"],
"isRemote": true,
"skills": ["Kubernetes", "Terraform", "AWS", "CI/CD", "Python"]
}
]salary is raw text — parse the first record's band into numerics, and skip "Depends on Experience" rows. jobLocation is structured (city, state, country) so you can group by metro without string-splitting locationDisplay. skills only appears when scrapeSkills is enabled; the second record shows that opt-in field populated.
Common pitfalls
Three things trip up production Dice pipelines. Salary is not always numeric — many listings carry "Depends on Experience" or no salary at all, so always test for a numeric pattern before aggregating, or your medians will be polluted by zeros and text. The skills list is opt-in — if your code expects a skills key on every row, it will break on runs where scrapeSkills is off; treat the field as optional and default to an empty list. Cross-board duplicates — the same role often appears on Dice, LinkedIn, and Indeed under different URLs, so when you aggregate, dedupe on a normalized (title, companyName, locationDisplay) tuple rather than detailsPageUrl alone.
Thirdwatch's actor returns salary as raw text (so nothing is silently coerced), keeps skills absent unless you ask for it, and exposes detailsPageUrl as a stable per-posting key for dedup — so each of these pitfalls is handled in the schema rather than left to you.
Related use cases
Frequently asked questions
Do I need a Dice login or API key to scrape Dice jobs?
No. The Dice Jobs Scraper reads Dice.com's public search results directly, so there is no login, API key, or token to manage. You pass a keyword and location, and the actor returns structured rows. Run it on demand or schedule it.
Are required skills included in the output?
The base listing returns title, company, location, salary, summary, and a remote flag. The per-job skills list is an optional extra step controlled by the scrapeSkills toggle. Turn it on and the actor fetches each job's detail page to populate the skills array, which is slower.
How complete is Dice's salary data?
Salary publication varies by query and over time. Many listings include a band like 'USD 130,000 - 160,000 per year', but some show 'Depends on Experience' or no salary at all. For compensation analysis, filter to rows with a numeric salary before aggregating and treat the rest as unknown.
How many jobs can I pull per search?
Set maxResults up to 1,000 per run. Dice returns roughly 20 jobs per page and the actor paginates until it hits your limit or exhausts the result set. For a multi-role recruiter sweep, run several keyword and location combinations and dedupe on the job's detail URL.
Does Dice cover roles outside US tech?
Dice is a US-focused technology job board, so coverage is strongest for software, data, cloud, security, and IT roles posted to the US market. It is not a general job board — for healthcare, retail, or non-US listings, pair it with broader sources like Indeed or LinkedIn.
How does Dice compare to LinkedIn and Indeed for tech sourcing?
Dice is narrower but denser on contract and full-time tech roles, including many staffing-firm and consultancy postings that LinkedIn underweights. Indeed has higher raw volume across all verticals. Most tech recruiting pipelines pull all three, dedupe by URL, and route candidates by skill and location downstream.
Related
100 free credits, no credit card.
About 30 real searches. Add the MCP to Claude or Cursor in two minutes.