# Dice Jobs Scraper — Tech Jobs & Salaries (`muhammadafzal/dice-jobs-scraper`) Actor

Scrape public Dice technology jobs by keyword, location, or URL. Returns normalized title, company, location, salary, work mode, employment type, description, dates, and job URLs for recruiting, market research, and job alerts. Not for profiles, applications, or private account data. $0.002/job.

- **URL**: https://apify.com/muhammadafzal/dice-jobs-scraper.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Categories:** Jobs, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 dice job results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Dice Jobs Scraper — Tech Jobs, Salaries & Descriptions

Scrape public Dice technology job listings by keyword, location, search URL, or job-detail URL. The Actor returns normalized hiring data for recruiting research, job alerts, salary analysis, talent-market mapping, and AI workflows without requiring a Dice login.

### What the Dice Jobs Scraper extracts

Each dataset item represents one globally deduplicated public Dice job.

| Field group | Included data |
|---|---|
| Job identity | Dice job ID, title, canonical job URL |
| Employer | Company name, Dice company URL, public logo URL |
| Location | Display location, city, state/region, postal code, country |
| Work terms | Remote/hybrid/on-site, normalized employment types, original employment label |
| Compensation | Displayed salary, numeric minimum/maximum, currency, original pay period |
| Content | Cleaned description up to 20,000 characters and public skill labels |
| Dates | Posted date, valid-through date, scrape timestamp |
| Application | Easy Apply flag and the public Dice apply/redirect URL |
| Provenance | Search keyword, search location, and source page |

The Actor writes run diagnostics to the `OUTPUT` key-value-store record instead of mixing warnings into the job dataset. `OUTPUT` includes page counts, discovered links, duplicates, filtered jobs, invalid records, event-cost estimates, and bounded warnings.

### When to use it

Use this Actor to:

- build current lists of US technology openings;
- monitor roles, companies, locations, remote work, and salary ranges;
- feed structured job data into a database, spreadsheet, ATS research workflow, or AI agent;
- schedule recurring Dice searches and compare newly posted jobs;
- retrieve one or more known public Dice job-detail URLs.

Do not use it for candidate profiles, résumé databases, account-only pages, automated applications, login workflows, or private employer data. It does not convert hourly salary to annual salary, because doing so would require assumptions about working hours.

### Input

| Input | Default | Purpose |
|---|---:|---|
| `searches` | Software engineer in New York | Up to 10 keyword/location searches. Set `[]` when using only start URLs. |
| `startUrls` | `[]` | Up to 100 public Dice search or job-detail URLs. |
| `maxResults` | `50` | Global unique-job cap across all sources, 1–1,000. |
| `maxPagesPerSearch` | `5` | Pagination cap per search URL, 1–20. |
| `includeDescription` | `true` | Keep the cleaned full public description. |
| `datePostedDays` | `0` | Keep jobs posted within 1–30 days; `0` disables the filter. |
| `workplaceTypes` | `[]` | Optional remote, hybrid, or on-site filter. |
| `employmentTypes` | `[]` | Optional full-time, part-time, contract, temporary, or internship filter. |
| `minimumSalary` | `0` | Require a disclosed salary maximum in its original pay period. |
| `proxyConfiguration` | No proxy | Standard Apify proxy configuration for networks where direct Dice access is restricted. |

#### Search example

```json
{
  "searches": [
    { "keyword": "data engineer", "location": "Austin, TX" },
    { "keyword": "Kubernetes", "location": "" }
  ],
  "maxResults": 100,
  "maxPagesPerSearch": 5,
  "workplaceTypes": ["remote", "hybrid"],
  "datePostedDays": 7,
  "includeDescription": true
}
```

#### Direct URL example

Input-schema defaults are applied by API runs, so explicitly send `"searches": []` for URL-only work.

```json
{
  "searches": [],
  "startUrls": [
    { "url": "https://www.dice.com/jobs?q=python&location=Boston%2C%20MA" },
    { "url": "https://www.dice.com/job-detail/5e054867-0c05-4336-9769-7f57b57bc261" }
  ],
  "maxResults": 25
}
```

Run through the Apify API with your own token in an authorization header:

```bash
curl -X POST "https://api.apify.com/v2/acts/YOUR_USERNAME~dice-jobs-scraper/runs?waitForFinish=120" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searches":[{"keyword":"cloud engineer","location":"Seattle, WA"}],"maxResults":10}'
```

### Output example

```json
{
  "jobId": "db1dbf9e-ad2b-4ba6-a49f-9b1a51e4c28f",
  "title": "Software Engineer / Developer - Ruby on Rails",
  "companyName": "Tandym Tech",
  "companyUrl": "https://www.dice.com/company-profile/dedfdf09-35e7-5124-b13c-7469202490be",
  "companyLogoUrl": "https://d3qscgr6xsioh.cloudfront.net/example.png?format=webp",
  "location": "Queens, NY, 11415, US",
  "locationCity": "Queens",
  "locationRegion": "NY",
  "postalCode": "11415",
  "countryCode": "US",
  "workplaceType": "on-site",
  "employmentTypes": ["contract"],
  "employmentTypeText": "CONTRACTOR",
  "salaryText": "$70 - $70 per hour",
  "salaryMin": 70,
  "salaryMax": 70,
  "salaryCurrency": "USD",
  "salaryUnit": "hour",
  "description": "A services organization is seeking a Full Stack Developer...",
  "skills": ["Ruby on Rails"],
  "datePosted": "2026-08-28T16:13:25.000Z",
  "validThrough": "2026-09-28T16:13:25.000Z",
  "easyApply": true,
  "applyUrl": "https://www.dice.com/dashboard/login?redirectUrl=%2Fjob-applications%2Fexample%2Fwizard",
  "jobUrl": "https://www.dice.com/job-detail/db1dbf9e-ad2b-4ba6-a49f-9b1a51e4c28f",
  "searchKeyword": "software engineer",
  "searchLocation": "New York, NY",
  "sourcePage": 1,
  "scrapedAt": "2026-08-29T12:00:00.000Z"
}
```

### Pay-per-event pricing

| Event | Price |
|---|---:|
| Actor start | $0.00005 per run |
| Dice job result | $0.002 per unique dataset item |

The result event is Apify's synthetic default-dataset-item event. It is charged automatically only after a schema-valid job is written, so the Actor does not manually double-charge records. A 50-job run costs about **$0.10005** in Actor events; a one-job run costs about **$0.00205**. Platform usage is intended to be included rather than passed through separately. Your run's maximum-charge setting can stop delivery earlier.

### Reliability and limits

Dice currently serves search cards and `JobPosting` JSON-LD in public server-rendered HTML, so the Actor uses direct HTTP with a coherent browser identity. This is faster and less expensive than a headless browser. It retries transient failures, uses consistent sessions, deduplicates job IDs before dataset writes, persists progress during migration, and stops at result or charge limits.

If Dice returns a challenge, rate limit, or changed page shape, the Actor preserves valid partial results and writes a classified warning to `OUTPUT`. A valid search with no matches returns an empty dataset and a truthful `EMPTY` summary. Configure Apify Proxy only when direct access from your run is restricted; proxy traffic can add platform cost.

Search results and job fields can change after posting. Some employers omit salary, work mode, postal code, application URL, skills, or expiration dates; those fields are returned as `null` or empty arrays rather than guessed. Filters that require missing data exclude that job.

### Legal and responsible use

Only public Dice pages are accessed. Use the data in accordance with Dice's terms, robots directives, applicable law, and your contractual obligations. Do not use the Actor to discriminate unlawfully, spam employers, automate applications, reidentify people, or collect account-only information. Job descriptions may contain employer-provided text; respect copyright and retain only what your use case requires.

For support, open an issue from the Actor page with the run ID, a redacted input example, the expected outcome, and the `OUTPUT` warning. Never include an Apify token, proxy password, cookie, or private applicant data.

# Actor input Schema

## `searches` (type: `array`):

Use this for one or more Dice keyword/location searches. Enter objects such as {"keyword":"software engineer","location":"New York, NY"}. Defaults to one working US search and accepts 0–10 searches. Set \[] when using only start URLs; this is not a list of applicant profiles.

## `startUrls` (type: `array`):

Use this for public dice.com/jobs search URLs or dice.com/job-detail/... URLs. Paste URLs such as https://www.dice.com/jobs?q=python or a specific job page. Defaults to \[]; this does not accept employer dashboards, login pages, or non-Dice URLs.

## `maxResults` (type: `integer`):

Use this to cap unique dataset records across every search and URL. Enter an integer such as 100. Defaults to 50 and accepts 1–1,000; at $0.002 per job this is the main event-cost cap, not a per-search limit.

## `maxPagesPerSearch` (type: `integer`):

Use this to bound Dice pagination for each search URL. Enter an integer such as 5. Defaults to 5 and accepts 1–20; each page currently exposes about 20 job links. This does not limit direct job-detail URLs.

## `includeDescription` (type: `boolean`):

Use this when downstream analysis needs the cleaned public job description. Defaults to true and caps text at 20,000 characters. Disable it for smaller records; this does not skip job-detail requests because filters use detail metadata.

## `datePostedDays` (type: `integer`):

Use this to keep jobs posted within a recent number of days based on Dice's ISO date. Enter 0 to disable or 1–30 days; for example 7 keeps the last week. Defaults to 0. This is not the Actor schedule interval.

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

Use this to keep selected Dice work arrangements. Choose any of remote, hybrid, or on-site. Defaults to \[] for all arrangements; missing work-mode labels remain eligible only when no selection is supplied.

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

Use this to keep selected normalized employment types from Dice. Choose full-time, part-time, contract, temporary, or internship. Defaults to \[] for all types; this is not a work-location filter.

## `minimumSalary` (type: `integer`):

Use this to require the disclosed Dice salary maximum to meet a numeric threshold in its original pay period, such as 60 for $60/hour. Defaults to 0 (disabled). Jobs without salary remain eligible only when this is 0; this does not convert hourly pay to annual pay.

## `proxyConfiguration` (type: `object`):

Use this if direct Dice requests are restricted from your network. Configure Apify or custom proxies in the standard proxy editor. Defaults to no proxy because Dice currently serves public HTML directly; this is not a job-location setting.

## Actor input object example

```json
{
  "searches": [
    {
      "keyword": "software engineer",
      "location": "New York, NY"
    }
  ],
  "startUrls": [],
  "maxResults": 100,
  "maxPagesPerSearch": 5,
  "includeDescription": true,
  "datePostedDays": 7,
  "workplaceTypes": [],
  "employmentTypes": [],
  "minimumSalary": 60,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Schema-valid unique Dice jobs with company, location, salary, work mode, dates, description, and source URLs.

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

Final search, pagination, deduplication, filtering, billing, and warning information.

# 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 = {
    "searches": [
        {
            "keyword": "software engineer",
            "location": "New York, NY"
        }
    ],
    "startUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/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 = {
    "searches": [{
            "keyword": "software engineer",
            "location": "New York, NY",
        }],
    "startUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/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 '{
  "searches": [
    {
      "keyword": "software engineer",
      "location": "New York, NY"
    }
  ],
  "startUrls": []
}' |
apify call muhammadafzal/dice-jobs-scraper --silent --output-dataset

```

## MCP server setup

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