# Dice Jobs Scraper (`steadyscrape/dice-jobs-scraper`) Actor

Scrape Dice (dice.com) US tech jobs and IT contracts: title, company, recruiter or direct employer, contract, C2C or full-time, W2 terms, remote or hybrid, salary or hourly rate, skills and full description. Search by keyword and city. Export to JSON, CSV or Excel, or via API.

- **URL**: https://apify.com/steadyscrape/dice-jobs-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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.

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

## Dice Jobs Scraper

Scrape tech jobs and IT contracts from **[Dice](https://www.dice.com)** (dice.com), the US job board for software, data,
cloud, cybersecurity and IT roles. This Dice jobs scraper searches Dice by **keyword**, **city or state** and **employment
type** (Contract, Third Party / C2C, Full-time, Part-time) and gives every job with its **company**, whether it was posted by
the **direct employer or a recruiter**, its **workplace type** (remote, hybrid, on-site), its **pay parsed into a minimum,
a maximum and an hourly or yearly period**, its location and dates — and, from each job's own page, the **full
description**, the **skills**, the **contract terms Dice shows (W2, Corp-to-Corp, Independent and the contract length)**,
the date Dice lists the job until and the employer's own job reference.

Built for IT staffing and consulting firms watching contract demand, recruiters sourcing requirements, and anyone tracking
the US tech job market. No login, no browser, no proxy, no start fee. Pay only for the jobs you get.

### What you can do with this Dice scraper

- **Contract and C2C requirements for staffing firms**: every Java, .NET, SAP, Salesforce or data contract in a state, with
  its hourly rate, W2 or corp-to-corp terms and contract length, split into direct clients and recruiters.
- **Bench sales and lead lists**: which employers are hiring contractors for which skills, where, and at what rate.
- **Rate and salary benchmarking**: published hourly rates and salaries by skill, city, employment type and workplace.
- **Job alerts and feeds**: schedule it daily with **Posted within** and **Only new jobs** to receive just the jobs posted
  since the last run.
- **Tech labour-market research**: contract vs full-time demand, remote vs on-site, skills employers ask for.

### Input

| Field | What it does |
|---|---|
| **Keywords** | `Java`, `Python Developer`, `DevOps`, `Data Engineer`, `SAP`, `Salesforce`, `C++`… each read through Dice's own page for it. |
| **Locations** | A US city (`Dallas`, `Dallas, TX`), a state (`Texas`), a city with its ZIP (`Beverly Hills, CA 90210`), a Canadian or UK city, or `Remote`. Each keyword is searched in each location; empty searches the whole US. |
| **Dice search links** | Searches copied from dice.com with their filters, e.g. `https://www.dice.com/jobs?q=java&location=Texas&filters.employmentType=CONTRACTS`. |
| **Employment types** | Contract, Third Party (C2C), Full-time, Part-time. Each type chosen is its own list, and a job under two types is delivered once. |
| **Employer type** | Direct employers only, recruiters and staffing firms only, or both. |
| **Workplace types** | Remote, hybrid, on-site. |
| **Posted within** | Today, the last 3 days or the last 7 days. |
| **Only employers willing to sponsor a visa** | Dice's "Willing to Sponsor" filter. |
| **Distance around a city** | 10, 30 (Dice's default), 50 or 75 miles. |
| **Minimum hourly rate / Minimum yearly salary** | Jobs whose published pay reaches it; hourly rates and salaries are compared at 2,080 hours a year when only one minimum is set. |
| **Only jobs with a pay in figures** | Leaves out "Depends on Experience", "DOE" and cards without pay. |
| **Include job details** | On by default: opens each job's page (charged as job-with-details). |
| **Max jobs per search** | 100 by default; 0 for every job Dice shows (at most 500 a search). |
| **Only new jobs since the last run** | Monitor mode for scheduled runs: jobs delivered before are skipped and not charged. |

Example — Java and Python contracts (including C2C) in Texas and remote, from direct employers, posted this week, paying at
least US$60 an hour:

```json
{
    "keywords": ["Java", "Python Developer"],
    "locations": ["Texas", "Remote"],
    "employmentTypes": ["CONTRACTS", "THIRD_PARTY"],
    "employerType": "direct",
    "postedWithin": "7",
    "minHourlyRate": 60,
    "maxJobsPerSearch": 200
}
```

### Output: Dice jobs data

One row per job (description shortened):

```json
{
    "rowType": "job",
    "status": "ok",
    "search": "Java · Contract",
    "searchUrl": "https://www.dice.com/jobs/q-java-jobs?filters.employmentType=CONTRACTS",
    "position": 2,
    "jobId": "c0e3a162-35ea-480d-95ad-f380f7a2041f",
    "legacyJobId": "5476a511375ca88e5b57ff838cbb67f9",
    "url": "https://www.dice.com/job-detail/c0e3a162-35ea-480d-95ad-f380f7a2041f",
    "title": "Senior Full Stack Java Developer",
    "companyName": "DatamanUSA, LLC",
    "companyLogo": "https://d3qscgr6xsioh.cloudfront.net/l4HgkVS5TpK9jYA9BWPD_da3afa7d28a7f36c9bd3ff1134c38127.png?format=webp",
    "companyProfileUrl": "https://www.dice.com/company-profile/5b5f17a9-11d0-5e3e-8012-1811cf3f335c",
    "companyDiceId": "10109429",
    "employmentTypes": ["Contract", "Third Party"],
    "employerType": "Direct Hire",
    "workplaceTypes": ["Remote", "On-Site"],
    "isRemote": true,
    "workFromHomeAvailable": false,
    "easyApply": true,
    "location": "San Jose, California, USA",
    "city": "San Jose",
    "state": "California",
    "stateCode": "CA",
    "country": "USA",
    "postedAt": "2026-10-27T14:18:49.000Z",
    "updatedAt": "2026-10-27T23:54:47.000Z",
    "salaryText": "USD 55-60",
    "salaryMin": 55,
    "salaryMax": 60,
    "salaryCurrency": "USD",
    "salaryPeriod": "hour",
    "salaryPeriodInferred": true,
    "summary": "DatamanUSA has an exciting opportunity for a Senior Full Stack Java Developer to work with one of our direct c…",
    "details": {
        "description": "DatamanUSA has an exciting opportunity for a Senior Full Stack Java Developer to work with one of ou…",
        "descriptionHtml": "<p style=\"text-align: justify;\">…",
        "skills": ["React.js", "Java", "Spring", "REST", "Microservices", "Oracle", "PL/SQL", "Docker", "Cloud", "Production Maintenance"],
        "contractTypes": ["W2", "Independent", "Corp-to-Corp"],
        "contractTerm": "12 Months",
        "employmentTypesSchema": ["CONTRACTOR"],
        "remoteAllowed": true,
        "datePosted": "2026-10-27T14:18:49.000Z",
        "validThrough": "2026-11-28T00:54:47.000Z",
        "postalCode": "95101",
        "applicantCountries": ["USA"],
        "positionId": "DatamanUSA - 9406-9412-1793110419"
    },
    "scrapedAt": "2026-10-28T13:10:00.000Z"
}
```

A search that finds nothing, a place Dice does not recognise, a link that cannot be read, or a page Dice's robots.txt
closes gives one **free** row with `rowType: "status"` and the reason (`no_results`, `not_found`, `invalid`, `disallowed`,
`blocked`, `unreadable`). The run's `SUMMARY` record gives, per search, Dice's own count of its jobs, the place Dice searched, how many
jobs each filter left out, and whether the search has more jobs than the 500 Dice shows.

### Dice job fields

| Field | Meaning |
|---|---|
| `jobId`, `legacyJobId`, `url`, `title` | Dice's job id (the one in the job's link), its older id, the job's page and title |
| `companyName`, `companyLogo`, `companyProfileUrl`, `companyDiceId` | The employer, its Dice company profile and its Dice account id |
| `employmentTypes` | `Full-time`, `Part-time`, `Contract`, `Third Party` (a job often has several) |
| `employerType` | `Direct Hire` (the employer itself), `Recruiter` (a staffing firm posting for a client) or `Other` |
| `workplaceTypes`, `isRemote`, `workFromHomeAvailable` | `Remote`, `Hybrid`, `On-Site`, and Dice's remote and work-from-home flags |
| `easyApply` | The job takes Dice's one-click application |
| `location`, `city`, `state`, `stateCode`, `country` | Where the job is; `null` on remote jobs that name no place |
| `postedAt`, `updatedAt` | When the job was posted and last updated (ISO 8601, UTC) |
| `salaryText` | The pay as the employer wrote it: `USD 55-60`, `$$67 - $69`, `USD 120,001.00 - 160,000.00 per year`, `Depends on Experience` |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | Its figures, currency and period (`hour`, `day`, `week`, `month`, `year`) |
| `salaryPeriodInferred` | The text named no period and it was told from the figures: under 500 hourly, from 10,000 yearly |
| `summary` | The first ~500 characters of the description |
| `search`, `searchUrl`, `position` | Which search found the job, the list it read and the place in it |
| `details.description`, `details.descriptionHtml` | The full job description, as text and as HTML |
| `details.skills` | The skills Dice lists for the job |
| `details.contractTypes`, `details.contractTerm` | The contract arrangements accepted (`W2`, `Corp-to-Corp`, `Independent`) and the contract length as written |
| `details.employmentTypesSchema`, `details.remoteAllowed` | schema.org employment types (`FULL_TIME`, `CONTRACTOR`…) and whether the job can be done remotely |
| `details.datePosted`, `details.validThrough` | When the job was posted and until when Dice lists it |
| `details.postalCode`, `details.applicantCountries` | The job's postal code and the countries applicants may live in |
| `details.positionId` | The employer's own reference for the job |
| `rowType`, `status`, `scrapedAt` | `job` with `ok`, or `status` with `no_results`, `not_found`, `invalid`, `disallowed`, `blocked`, `unreadable`; and when the row was read (ISO 8601, UTC) |
| `url`, `reason` (status rows) | The page or link the status is about, and why it gave no jobs |

The apply box's e-mail address next to a job's contract terms is never read. Descriptions come as the employer wrote them,
and a recruiter's post sometimes names a contact person in its own text.

### Pricing

| Event | Price |
|---|---|
| `job` — a job as its search list shows it | US$0.001 |
| `job-with-details` — a job read with its own page | US$0.002 |
| Status rows (nothing found, unknown place, bad link) and jobs your filters leave out | free |

No start fee. Set a maximum cost per run in Apify and the Actor stops at what it can pay for.

### Limits

- **Dice shows at most 500 jobs of one search** (25 pages of 20). A search with more says so in the run's summary; split it
  by location, employment type or a narrower keyword to get more. Each employment type you choose is already its own search.
- **Dice's keyword search page is closed to crawlers** by its robots.txt (`/jobs?q=`), so this Actor reads Dice's keyword
  and location pages instead (`/jobs/q-java-l-texas-jobs`), which Dice publishes in its sitemaps and which carry the same
  jobs and filters. It obeys robots.txt on every request.
- **Dice includes remote jobs in place searches**, as its own site does: a search in Texas also lists remote jobs based
  elsewhere. Add the On-site or Hybrid workplace filter to keep only jobs in the place.
- Dice lists by relevance, not date: use **Posted within** for the newest jobs.
- Pay is written freely by employers; when the text names no period (`USD 55-60`), `salaryPeriod` is told from the figures and
  `salaryPeriodInferred` is `true`.
- One request a second, one IP, no proxy: a run of 100 jobs with details takes about two minutes.

### Is it legal to scrape Dice?

This Actor reads only public job listings that anyone can open without an account, at a gentle pace, and follows Dice's
robots.txt. It collects nothing about candidates and leaves out the recruiter's application e-mail; a name or e-mail an
employer wrote into a job's description is personal data. Dice's terms of use restrict automated access: check them and the
laws that apply to you (GDPR or CCPA among them), especially before republishing data. This is an unofficial tool: it is not
affiliated with, endorsed or sponsored by Dice or DHI Group, Inc.

# Actor input Schema

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

What people type into Dice's search box: <code>Java</code>, <code>Python Developer</code>, <code>DevOps</code>, <code>Data Engineer</code>, <code>SAP</code>, <code>C++</code>, <code>Salesforce</code>. Each keyword is read through Dice's own page for it (dice.com/jobs/q-java-jobs). Hyphens are read as spaces ("front-end" as "front end"), because Dice's pages split words at hyphens.

## `locations` (type: `array`):

A US city (<code>Dallas</code>, <code>Dallas, TX</code>), a state (<code>Texas</code>), a city with its ZIP code (<code>Beverly Hills, CA 90210</code>), a Canadian or UK city, or <code>Remote</code> for remote jobs anywhere. Each keyword is searched in each location. Dice also lists remote jobs in every place search, as its own site does. A place Dice does not recognise gives a free row saying so, instead of jobs from everywhere. Leave empty to search the whole US.

## `searchUrls` (type: `array`):

Searches copied from dice.com, with their filters: <code>https://www.dice.com/jobs/q-java-l-texas-jobs?filters.employmentType=CONTRACTS</code> or <code>https://www.dice.com/jobs?q=java\&location=Texas\&filters.postedDate=ONE</code>. A keyword search link is read through Dice's page for the same keyword and place (its robots.txt closes the search page itself to crawlers).

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

Dice's own employment type filter. Each type chosen is searched as its own list (Dice shows at most 500 jobs of one search), and a job listed under two types is delivered once. "Third Party" is a job a corp-to-corp (C2C) contractor may take. Leave empty for all types in one list.

## `employerType` (type: `string`):

Direct employers only, staffing firms and recruiters only, or both.

## `workplaceTypes` (type: `array`):

Remote, hybrid or on-site jobs, through Dice's own filter. Leave empty for all.

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

Dice's own posted date filter.

## `willingToSponsor` (type: `boolean`):

Dice's "Willing to Sponsor" filter.

## `radiusMiles` (type: `string`):

Miles around each location (Dice searches 30 by default).

## `minHourlyRate` (type: `integer`):

For contracts: jobs whose pay reaches this rate an hour. A yearly salary is counted at 2,080 hours a year unless a minimum yearly salary is also set. Jobs without a pay in figures ("Depends on Experience") are left out when it is set. Left-out jobs are not charged.

## `minYearlySalary` (type: `integer`):

For full-time jobs: jobs whose pay reaches this salary a year (an hourly rate counted at 2,080 hours, unless a minimum hourly rate is also set, which then applies to hourly pay).

## `onlyWithSalary` (type: `boolean`):

Leaves out jobs whose card shows no pay, or only words such as "Depends on Experience" or "DOE".

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

On by default: opens each job's page for the full description, the skills, the contract terms (W2, Corp-to-Corp, Independent and the contract length), the date Dice lists the job until, the postal code and the employer's own job reference. Charged as job-with-details; off, each job is charged as job.

## `maxJobsPerSearch` (type: `integer`):

Per keyword, location and employment type. 0 for every job Dice shows (at most 500 a search: Dice shows 25 pages of 20).

## `onlyNewJobs` (type: `boolean`):

Monitor mode for scheduled runs: jobs an earlier run with the same searches and filters delivered are skipped and not charged.

## Actor input object example

```json
{
  "keywords": [
    "Java"
  ],
  "locations": [],
  "searchUrls": [],
  "employmentTypes": [
    "CONTRACTS"
  ],
  "employerType": "any",
  "workplaceTypes": [],
  "postedWithin": "any",
  "willingToSponsor": false,
  "radiusMiles": "30",
  "onlyWithSalary": false,
  "includeDetails": true,
  "maxJobsPerSearch": 20,
  "onlyNewJobs": false
}
```

# Actor output Schema

## `jobs` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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": [
        "Java"
    ],
    "employmentTypes": [
        "CONTRACTS"
    ],
    "maxJobsPerSearch": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/dice-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": ["Java"],
    "employmentTypes": ["CONTRACTS"],
    "maxJobsPerSearch": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/dice-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": [
    "Java"
  ],
  "employmentTypes": [
    "CONTRACTS"
  ],
  "maxJobsPerSearch": 20
}' |
apify call steadyscrape/dice-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/dice-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/XwhjjtyMniFIVUtHz/builds/FXP59Xi8iqi8UQ0Qg/openapi.json
