# Dice Scraper (`mlg14/dice-scraper`) Actor

Collect Dice technology jobs by keyword, location, posting date, and remote preference. Export titles, companies, pay, descriptions, dates, and job links.

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

## Pricing

$0.80 / 1,000 results

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 Scraper

Scrape Dice technology jobs by keyword, location, posting date, and remote preference. Export Dice job data to JSON, CSV, or Excel for hiring research, salary analysis, and recurring vacancy monitoring. This Dice API alternative collects public listing fields and, when available, the full job description from each posting page.

Each result is one job. Records contain a stable job identifier, employer and location, compensation text, workplace setting, dates, source links, and search context. A run stops when it reaches your result target, its page limit, the available public listings, or the run's event budget.

### What data can you extract from Dice?

The output is a flat record that works in a spreadsheet or a data pipeline. Empty values mean that a particular listing did not provide the field. The description fields are collected from the job's public detail page; other fields primarily come from the structured search result.

| Field | Description | Example |
| --- | --- | --- |
| `id` | Listing identifier from the search result | `150419adb6ec201f68e36f4b8b77dd8f` |
| `jobId` | Job identifier, matching `id` | `150419adb6ec201f68e36f4b8b77dd8f` |
| `guid` | Public job GUID used in the detail URL | `752dc96c-9c33-4663-9022-eb23370623f6` |
| `diceId` | Convenient alias for the public GUID | `752dc96c-9c33-4663-9022-eb23370623f6` |
| `dice_id` | Compatibility alias for `diceId` | `752dc96c-9c33-4663-9022-eb23370623f6` |
| `positionId` | Source position ID, falling back to `id` | `150419adb6ec201f68e36f4b8b77dd8f` |
| `position_id` | Compatibility alias for `positionId` | `150419adb6ec201f68e36f4b8b77dd8f` |
| `title` | Published job title | `Python Developer` |
| `company` | Employer name | Varies by listing |
| `companyName` | Source employer name | Varies by listing |
| `companyPageUrl` | Public employer profile link | A Dice profile URL |
| `companyLogoUrl` | Published employer logo link | An image URL |
| `location` | Human-readable work location | `Atlanta, Georgia, USA` |
| `city` | City in structured location | `Atlanta` |
| `state` | State or region in structured location | `Georgia` |
| `country` | Country in structured location | `USA` |
| `salary` | Published compensation text | `USD 50.00 - 65.00 per hour` |
| `employmentType` | Employment arrangement | `Full-time` |
| `employerType` | Employer category | `Direct Hire` |
| `workSetting` | Published workplace type | `On-Site` |
| `isRemote` | Source remote indicator | `false` |
| `workFromHomeAvailability` | Source work-from-home indicator | `FALSE` |
| `summary` | Search result summary | A short description excerpt |
| `descriptionHtml` | Full description markup when available | Paragraphs and lists |
| `description_html` | Compatibility alias for `descriptionHtml` | Same markup |
| `descriptionText` | Readable full description, or summary fallback | Plain text |
| `description_text` | Compatibility alias for `descriptionText` | Same text |
| `posted` | Publication timestamp | `2026-09-25T23:02:47Z` |
| `updated` | Last modified timestamp | `2026-09-26T11:03:04Z` |
| `validThrough` | Posting expiration date when published | An ISO timestamp |
| `willingToSponsor` | Structured sponsorship flag if supplied | `null` when absent |
| `easyApply` | Source easy-apply indicator | `false` |
| `url` | Direct public job link | A Dice job-detail URL |
| `detailsPageUrl` | Original source detail link | Same job-detail URL |
| `searchId` | Identifier for the source search response | A search GUID |
| `searchPage` | Page on which the job was found | `1` |
| `searchPageSize` | Number of results on a source page | `30` |
| `searchSortBy` | Source ordering mode | `relevance` |
| `searchIncludeRemote` | Remote inclusion setting requested | `true` |
| `searchKeyword` | Keyword used for this run | `python` |
| `searchLocation` | Location input, if supplied | `New York, NY` |
| `source` | Source website | `dice.com` |

The paired camel-case and underscore fields are intentionally identical. They let existing job-data imports continue to read familiar column names while new workflows can use camel case. For a compact export, select only the columns you need after downloading the dataset. `summary` can be shorter than the full job description. `descriptionText` is the field to use for text analysis; `descriptionHtml` retains the posting's markup and list structure.

### How to scrape Dice jobs

1. Enter a role, technology, or skill in `keyword`. A focused phrase such as `python developer` usually gives a more useful result set than a broad term.
2. Optionally enter a location and choose a posting-date window. Leave location empty for a broad search.
3. Choose whether remote listings should be retained, then set `results_wanted`. Use `maxPages` when you want a strict page ceiling.
4. Run the scraper and review the dataset preview. Export the result as JSON, CSV, or Excel, or connect the completed dataset to another workflow.

Start with a modest result target to check how a keyword maps to actual vacancies. A search for a programming language can include jobs that mention the language in a long description rather than in the title. A role phrase narrows the results. Search results can change between runs as jobs are added, revised, or removed.

### Input

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `keyword` | String | `python` | Job title, skill, or phrase. |
| `location` | String | Empty | Optional city, state, region, or remote location text. |
| `posted_date` | String | `all` | `all`, `24h`, `3d`, `7d`, or `30d`. |
| `includeRemote` | Boolean | `true` | Retain remote jobs when true; remove remote jobs from saved results when false. |
| `results_wanted` | Integer | `20` | Maximum distinct jobs to save, from 1 to 10,000. |
| `maxPages` | Integer | `25` when omitted | Maximum search pages to inspect, from 1 to 25. |
| `proxyConfiguration` | Object | Enabled | Optional proxy configuration. |

Example input for a recent regional search:

```json
{
  "keyword": "python developer",
  "location": "Atlanta, GA",
  "posted_date": "7d",
  "includeRemote": false,
  "results_wanted": 60,
  "maxPages": 5
}
```

`results_wanted` is a maximum, not a guarantee. The scraper may find fewer jobs if the query has fewer public results, a location is narrow, remote exclusion removes many listings, or `maxPages` is reached. Omitting `maxPages` permits the scraper to inspect up to Dice's observed 25 distinct result pages. The input can accept a larger result target so the same schema remains useful for future changes, but one current search slice cannot reliably provide more than 25 pages of 30 jobs.

### Output example

This is a shortened view of a real job item from a 30-result validation run on September 26, 2026. The full record also included the description, employer, identifiers, search metadata, and source fields shown in the table above.

```json
{
  "id": "150419adb6ec201f68e36f4b8b77dd8f",
  "guid": "752dc96c-9c33-4663-9022-eb23370623f6",
  "title": "Python Developer",
  "location": "Atlanta, Georgia, USA",
  "salary": "USD 50.00 - 65.00 per hour",
  "employmentType": "Full-time",
  "workSetting": "On-Site",
  "posted": "2026-09-25T23:02:47Z",
  "updated": "2026-09-26T11:03:04Z",
  "url": "https://www.dice.com/job-detail/752dc96c-9c33-4663-9022-eb23370623f6",
  "searchPage": 1,
  "source": "dice.com"
}
```

An item with no published salary has `salary: null`; it does not receive an estimated value. A detail page that lacks a structured full description falls back to the listing summary in `descriptionText`. Keep `id` or `guid` as your deduplication key when combining runs. Job URLs are useful for review, but an expired posting may later stop displaying the same content.

### Use cases

- **Recruiting research:** Build a shortlist of recently posted roles by skill, city, and workplace setting. Keep the direct link with every record so a recruiter can verify a role before outreach.
- **Hiring demand monitoring:** Run the same query on a schedule and compare new GUIDs with the previous dataset to identify openings. Record the run time alongside `posted` because the site can update a listing after publication.
- **Compensation analysis:** Use listings with a published `salary` to study pay bands by role and region. Separate hourly and annual values before calculating averages; the source field is free-form text.
- **Workplace policy tracking:** Compare on-site, hybrid, and remote counts for a consistent keyword and location. Use `workSetting` and `isRemote` together when classifying ambiguous listings.
- **Regional market snapshots:** Search a set of metropolitan areas with the same role phrase and date window. Keep search location metadata so downstream tables can distinguish the requested region from a listing's actual workplace.
- **Vacancy enrichment:** Join the exported GUID, title, description, and employer profile link to an existing internal vacancy table. Preserve the source URL for verification and updates.

### How much does it cost to scrape Dice?

The event price configured for this scraper is **$0.80 per 1,000 saved jobs**, or $0.0008 per saved result. A 50-job dataset costs $0.04 in result charges; 250 jobs cost $0.20; 1,000 jobs cost $0.80. These examples assume the run reaches the requested count. Fewer saved jobs mean fewer result events. Platform usage is included in this result price for users of the scraper.

The number of pages visited does not directly determine the event charge, but pages and job details still take time to fetch. An exact run duration depends on page response times, the number of jobs, and whether the source is temporarily unavailable. In the validation run, 30 jobs with full descriptions completed successfully. For routine monitoring, set a smaller date window and a realistic result cap so the run does not revisit old listings unnecessarily.

### Tips for best results

Use precise keywords. `python developer` emphasizes developer openings; `python` can surface roles that mention the skill elsewhere. If a search is too narrow, remove the location first, then widen the posting-date window. If it is too broad, add a role qualifier or a city.

Use the date choices to split a large market into manageable runs. `24h` is appropriate for daily alerts when there are enough new jobs, while `7d` provides a broader weekly sample. `all` has the largest result set but reaches the 25-page cap sooner. Separate role or location searches can reveal additional listings beyond that cap. Deduplicate combined datasets by `guid`, because a job can appear in more than one search.

The source provides direct filters for the shorter date windows. For `30d`, the scraper checks each result's published timestamp against the previous 30 days because the public search page does not apply a 30-day query filter. That selection is limited by the same 25-page window as an unfiltered search. A broad keyword can therefore miss matching jobs beyond the visible pages.

When you exclude remote jobs, the scraper filters the returned records using the source remote flag and workplace type. That can require another page to reach your requested count. Check the `workSetting` and `isRemote` values when your definition of remote work differs from the source. A hybrid role is not automatically removed.

Choose `maxPages` for predictable sampling. With a page size of 30, a five-page limit inspects at most roughly 150 result slots before duplicates or remote filtering. Leave `maxPages` unset when the result target matters more than the number of page requests. Set `results_wanted` to the maximum number you actually plan to use, since each saved row counts as a result event.

For recurring datasets, keep the same input and compare identifiers across runs. A changed `updated` timestamp can indicate a revised listing, even when the GUID is unchanged. Do not infer that a role was filled solely because it disappeared from one query: it may have expired, moved in the ranking, or changed its search terms.

### Limits

Dice currently presents 30 records per search page and clamps requests beyond page 25 back to page 25. That yields an observed ceiling of about 750 result slots for one keyword, location, and date combination. The scraper stops at page 25 and deduplicates GUIDs. Broad searches should be split into meaningful roles, regions, or date windows when greater coverage is needed.

The public search page can provide a result count much larger than the number of distinct pages it exposes. This scraper does not claim to collect the full count shown for a broad query. Search ordering may also change between page requests as postings arrive. Duplicate suppression protects the dataset, but shifting rankings can still leave gaps in a single run.

Some listings omit location or salary. In the 30-job validation run, 27 records had a display location and 23 had salary text. All 30 had a title, employer, posting date, URL, and plain-text description. The structured sponsorship field was absent in that sample; a mention of sponsorship inside a description is not converted into a boolean. For a critical decision, verify the original posting.

Full descriptions require a separate public detail page per saved job. If a detail page fails temporarily, the listing can still be saved with its summary as text. Description markup comes from the posting and may contain formatting or wording that should be reviewed before publishing elsewhere. Pages, fields, filters, and source access can change over time.

### Use with automated workflows

The descriptive input fields and flat output let an automated workflow request a run, read its dataset, and then act on saved rows. Example requests:

> Find up to 50 Python developer jobs posted in the last seven days around Atlanta. Return the title, location, salary text, posted date, and source link for each.

> Collect recent on-site data engineering jobs, compare their GUIDs with yesterday's dataset, and report newly observed vacancies with their direct links.

When a workflow summarizes descriptions, retain each `url` so a reviewer can inspect the public source. If you join multiple searches, deduplicate before counting employers, salary ranges, or openings. A single posting can match several phrases and regions.

### FAQ

#### Is collecting Dice job data legal?

This scraper collects publicly visible job postings. Collection and downstream use can still be subject to website terms, privacy requirements, and local law. Use the data for legitimate research or recruiting, respect the source's policies, and avoid personal-data misuse.

#### Do I need to configure a proxy?

The default input enables a proxy. Most users can leave that setting unchanged. If public pages are temporarily unavailable, retry later or inspect the run log for the specific failure.

#### How fast is a run?

Duration depends on the number of listings and detail pages. A 30-job validation run completed successfully, but individual runs can vary with site response times. Start with 20 to 50 results to measure current conditions for your query.

#### Can I schedule recurring searches and monitor changes?

Yes. Save one input per role or region and run it on a schedule. Compare `guid` values with the prior dataset, then use `updated` to spot revised postings. Keep the same date window and filters when comparing counts.

#### Can I export to a spreadsheet?

Yes. Download the dataset as CSV or Excel, or retrieve JSON for a database. Text descriptions can be long, so choose the columns you need in a spreadsheet view. Salary is published text and may need normalization before formulas.

#### What does an empty field mean?

It usually means Dice did not publish that value in the accessible listing or detail data. Salary, location, and sponsorship are especially variable. Empty values are not filled with guesses.

#### Why did the run save fewer jobs than requested?

The public query may have too few matches, the page cap or your `maxPages` setting may be reached, remote filtering may remove records, or duplicates may appear across pages. Widen the search or use separate role and region slices when you need more coverage.

### Integrations

Retrieve the dataset through the platform API, export it to a spreadsheet, trigger a webhook after completion, or pass records to an automation service. Scheduled runs support recurring monitoring; the stable IDs make it straightforward to compare results with an internal table. For reporting, retain query inputs and run dates with the exported rows so later readers know the scope of each snapshot.

### Support

Open an issue on the Issues tab; we reply within 24h and add fields on request.

# Actor input Schema

## `keyword` (type: `string`):

Job title, skill, or phrase to search for.

## `location` (type: `string`):

Optional city and state (e.g. Austin, TX) to get jobs within 30 miles, or "Remote" for remote-only jobs. Leave empty for all of the US.

## `posted_date` (type: `string`):

Show jobs posted within the chosen time window.

## `includeRemote` (type: `boolean`):

Include remote listings. When disabled, remote jobs are removed from the saved results.

## `results_wanted` (type: `integer`):

Maximum number of distinct jobs to save.

## `maxPages` (type: `integer`):

Optional search-page limit; Dice exposes at most 25 distinct pages per query.

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

Proxy settings for public Dice pages.

## Actor input object example

```json
{
  "keyword": "python",
  "location": "New York, NY",
  "posted_date": "7d",
  "includeRemote": true,
  "results_wanted": 50,
  "maxPages": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Saved jobs in the default dataset.

# 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 = {
    "keyword": "python",
    "location": "New York, NY",
    "posted_date": "7d",
    "includeRemote": true,
    "results_wanted": 50,
    "maxPages": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/dice-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 = {
    "keyword": "python",
    "location": "New York, NY",
    "posted_date": "7d",
    "includeRemote": True,
    "results_wanted": 50,
    "maxPages": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("mlg14/dice-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 '{
  "keyword": "python",
  "location": "New York, NY",
  "posted_date": "7d",
  "includeRemote": true,
  "results_wanted": 50,
  "maxPages": 3
}' |
apify call mlg14/dice-scraper --silent --output-dataset

```

## MCP server setup

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