# DFS Player Props API — PrizePicks & Underdog (`lergassy/dfs-props-scraper`) Actor

Every player prop on PrizePicks and Underdog Fantasy in one table: player, team, stat, line, payout type, over and under prices with implied probability — plus a compare mode that pairs the same player and stat across both apps and shows which one asks for less. No login, no proxy.

- **URL**: https://apify.com/lergassy/dfs-props-scraper.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** Developer tools, Automation, Sports
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.07 / 1,000 player props

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

**DFS Player Props API** reads the PrizePicks and Underdog Fantasy boards and returns every player prop as one table: player, team, league, stat, line, payout type, and — where the app publishes them — the over and under prices with implied probabilities. No account, no cookies, no proxy, no browser.

![One run of DFS Player Props API: PrizePicks and Underdog lines for the same slate side by side.](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/dfs-props-scraper/dfs-props-scraper-output-table.png)

Three modes: **props** (the full board), **compare** (the same player and stat on both apps, with the line difference), and **leagues** (what has an open board right now).

### What is DFS Player Props API?

PrizePicks and Underdog are the two big pick'em apps: instead of betting against a sportsbook you say whether a player will go over or under a number. The number is the product, and the two apps rarely publish the same one — which is why anyone serious about pick'em keeps both open.

This Actor turns both boards into data, in one shape, so you can filter, sort, chart or feed them to a model.

### What makes it different

**A comparison that survives contact with the real boards.** Joining the two apps on player and stat sounds trivial and produces nonsense, for two reasons this Actor handles explicitly:

- The apps abbreviate stats differently — "Rec Yards" against "Receiving Yards", "Recs" against "Receptions". Fuzzy matching happily equates "Rush+Rec Yds" with "Receiving Yards", so the names go through an explicit table instead.
- PrizePicks lists the same player and stat many times over: one standard line plus a ladder of **demon** (harder, pays more) and **goblin** (easier, pays less) lines. Only the standard line is comparable to Underdog's balanced line, so that is the one the comparison uses — and the row tells you how many alternates exist behind it.

Season-long and part-of-game boards (NFLSZN, NFL1H, MLBLIVE) are kept out of an unfiltered run for the same reason: they carry identical player and stat names and would pair a season total against a single game.

**Fantasy points are deliberately left out of the comparison.** Each app scores a game with its own formula, so their lines differ by a couple of points on every player. That is a difference of definition, not of opinion. The props mode still returns them.

### What data does it return?

#### Props

| Field | Example |
|---|---|
| `platform`, `propId` | prizepicks · 14636851 |
| `league`, `player`, `team`, `teamName`, `position` | NFL · Rhamondre Stevenson · NE · New England Patriots · RB |
| `market`, `line` | Rush Yards · 57.5 |
| `oddsType`, `pickType`, `allowedPicks` | standard / demon / goblin · Single Stat · over |
| `overPrice`, `underPrice` | +139 · −113 (Underdog) |
| `overDecimal`, `underDecimal`, `overImplied`, `underImplied` | 2.39 · 1.88 · 41.8 · 53.2 |
| `overMultiplier`, `underMultiplier` | 1.27 (Underdog payout multiplier) |
| `live`, `promo`, `status`, `gameId`, `opponent` | false · false · pre\_game · … |
| `startTime`, `updatedAt`, `image`, `url` | ISO 8601 · … |

PrizePicks quotes a payout **type** rather than a price: standard is the plain line, a demon pays more for a harder number, a goblin pays less for an easier one. Underdog quotes American prices and a payout multiplier. On a single-app run the columns the other app owns are dropped rather than served empty.

#### Compare

One row per player and stat listed on both apps: `prizePicksLine`, `underdogLine`, `lineDifference`, `easierOver` (which app has the shorter line, and therefore the easier over), `prizePicksAlternateLines`, Underdog's prices, and the kick-off time.

### How much does it cost?

Pay per row, and only for rows you actually get:

| Event | Price |
| --- | --- |
| Prop | $0.0001 |
| Comparison | $0.002 |
| League row | $0.0002 |

**Error rows are never charged, and there is no charge for starting a run.** Two public JSON APIs, no browser and no proxy, so platform usage is negligible.

| Job | Cost |
| --- | --- |
| 1,000 props across both apps | $0.10 |
| A full comparison of an NFL slate (≈50 pairs) | $0.10 |
| A 500-prop snapshot every hour for a day | $1.20 |

Other props Actors charge less per row but $0.01 to $0.05 for every run, which is the whole
cost on a small pull. This one is priced per row only.

### How to use it

1. Choose **🎯 Apps** — keep both for one table across the two boards.
2. Choose **📋 What to get**: props, compare, or the league list.
3. Narrow with **🏆 Leagues**, **🧍 Players** or **📊 Stats** — all partial matches.
4. Click **Start**, then export as JSON, CSV or Excel, or read the dataset through the API.

![The input form of DFS Player Props API: apps, mode, leagues, players and stat filters.](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/dfs-props-scraper/dfs-props-scraper-input-form.png)

### ⬇️ Input

```json
{
  "platforms": ["prizepicks", "underdog"],
  "mode": "props",
  "leagues": ["NFL"],
  "maxRows": 1000
}
```

#### Line shopping across both apps

```json
{ "mode": "compare", "maxRows": 200 }
```

#### One player, everything on the board

```json
{ "mode": "props", "players": ["Mahomes"], "maxRows": 100 }
```

#### One stat across a league

```json
{ "mode": "props", "leagues": ["NBA"], "markets": ["Points", "Rebounds"] }
```

### ⬆️ Output

```json
{
  "type": "prop",
  "platform": "underdog",
  "propId": "91793ff7-a541-4948-a4b8-218cd3a5ae18",
  "league": "NFL",
  "player": "A.J. Brown",
  "team": "NE",
  "teamName": "New England Patriots",
  "market": "Rush + Rec TDs",
  "line": 0.5,
  "oddsType": "balanced",
  "pickType": "Over/Under",
  "overPrice": "+139",
  "underPrice": "-181",
  "overDecimal": 2.39,
  "underDecimal": 1.5525,
  "overImplied": 41.8,
  "underImplied": 64.4,
  "overMultiplier": 1.27,
  "startTime": "2026-09-10T00:20:00.000Z",
  "url": "https://underdogfantasy.com/pick-em",
  "scrapedAt": "2026-09-09T13:00:00.000Z"
}
```

A board that fails to answer arrives as a `type: "error"` row with the reason, never as a silently short list.

### Use cases

#### Line shopping

Run the compare mode before you build a slip and take the shorter line for an over, the longer one for an under.

#### Model inputs

Feed the board into your own projections and look for the stats where the apps are furthest from your number.

#### Tracking how lines move

Schedule the Actor and keep a history of a slate from board release to kick-off.

#### Content and newsletters

The compare table is a ready-made "where the apps disagree today" section.

#### AI agents

An agent asked "what's the line on Mahomes passing yards" runs the props mode with a player filter and reads `line` and `platform` off the rows.

### 🤖 For AI Agents & LLM Apps

Compact reference for agents calling this Actor through the [Apify MCP server](https://mcp.apify.com) or the Apify API (`lergassy/dfs-props-scraper`).

**Minimal input:**

```json
{ "mode": "props", "players": ["Mahomes"], "maxRows": 50 }
```

**Behaviors an agent should know:**

- **PrizePicks has no prices.** It publishes a payout type: `standard`, `demon` (harder, pays more) or `goblin` (easier, pays less). Quote `oddsType`, never an implied probability, for PrizePicks rows.
- **Underdog has prices**, American in `overPrice`/`underPrice`, decimal and implied alongside.
- One player and stat can appear several times on PrizePicks at different lines. The standard one is the board line; the rest are boosted alternates.
- In compare mode, `easierOver` names the app with the shorter line — the easier side for an over, and the harder one for an under.
- Fantasy points are excluded from comparisons because the two apps score them differently.
- Without a league filter, PrizePicks boards are taken from the biggest ones down to `maxLeagues` (three by default): the app rate-limits rapid requests and a single NFL board is several megabytes. Name a league to lift that.
- Underdog's search endpoint returns at most 100 lines per sport and ignores paging, so its side is the top of each sport's board rather than all of it.
- Both boards are public: no key, no account, no proxy.

### PrizePicks API and Underdog API without a login

Both apps serve their boards as JSON. PrizePicks answers 403 to a filtered request on its main host and 429 to bursts, so this Actor uses the partner host, spaces its requests and retries a rate limit slowly instead of hammering it. Underdog's payload keeps lines, appearances, players, teams and games in separate lists that have to be stitched back together by id.

### ❓ FAQ

#### Is this gambling advice?

No. It reads public board data and returns it as a table. It places no entries and gives no picks.

#### Why do PrizePicks and Underdog show different numbers for the same player?

Different projection models, different customer bases and different payout structures. That gap is exactly what the compare mode is for.

#### What are demon and goblin lines?

PrizePicks' boosted alternates: a demon is a harder number that pays more, a goblin an easier one that pays less. Both sit on the same player and stat as the standard line.

#### Do I need an account on either app?

No. The endpoints used here are public and read-only.

#### How fresh are the numbers?

Live at the moment of the run. Boards move all day, so schedule the Actor if you want a history.

#### Can I use it with the Apify API or an MCP server?

Yes. It runs from the API and the official clients, and AI agents reach it through the Apify MCP server without extra setup.

### Your feedback

Missing an app or a stat mapping? Open an issue on the **Issues** tab — every one gets answered.

### You might also like

| Actor | What it does |
|---|---|
| [Sports Betting Odds API](https://apify.com/lergassy/sports-odds-api) | Bookmaker lines, arbitrage and value bets |
| [Sports Injury Report API](https://apify.com/lergassy/sports-injuries-api) | Who is out, questionable or probable |
| [Kalshi Scraper & API](https://apify.com/lergassy/kalshi-scraper) | Prediction market odds on anything |
| [Sports Scores & Schedules API](https://apify.com/lergassy/sports-scores-api) | Live scores and schedules for 33 leagues |

### Also known as

People look for this Actor as a PrizePicks API, an Underdog Fantasy API, a DFS props scraper, player props data, pick'em lines, prop betting lines and a fantasy props feed.

# Actor input Schema

## `platforms` (type: `array`):

Which boards to read. Keep both to get one table across the two biggest pick'em apps.

## `mode` (type: `string`):

<b>Props</b> is the full board. <b>Compare</b> keeps only players listed on both apps and shows the line difference — the shorter line is the easier side of the same bet.

## `leagues` (type: `array`):

Leave empty to take the biggest boards (see the league cap below). Partial names work: <code>NBA</code>, <code>NFL</code>, <code>MLB</code>, <code>SOCCER</code>, <code>UFC</code>, <code>TENNIS</code>. In compare mode this also decides which sports are matched across the two apps.

## `players` (type: `array`):

Filter to specific players by name, in part or in full: <code>Mahomes</code>, <code>Shai Gilgeous-Alexander</code>.

## `markets` (type: `array`):

Filter to specific stat types: <code>Points</code>, <code>Rebounds</code>, <code>Passing Yards</code>, <code>Strikeouts</code>.

## `maxLeagues` (type: `integer`):

With no league named, PrizePicks boards are taken from the biggest ones down to this many. PrizePicks rate-limits rapid requests and a single NFL board is several megabytes, so pulling every league at once is slow and often refused. Naming leagues above lifts this cap.

## `maxRows` (type: `integer`):

Cap on rows per run. A busy NBA and NFL evening puts several thousand props on the two boards together.

## Actor input object example

```json
{
  "platforms": [
    "prizepicks",
    "underdog"
  ],
  "mode": "props",
  "leagues": [],
  "maxLeagues": 3,
  "maxRows": 1000
}
```

# Actor output Schema

## `props` (type: `string`):

One row per prop with the app, player, team, league, stat, line, payout type, over and under prices and implied probabilities. Compare mode returns one row per player and stat listed on both apps with the line difference.

# 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 = {
    "leagues": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/dfs-props-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 = { "leagues": [] }

# Run the Actor and wait for it to finish
run = client.actor("lergassy/dfs-props-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 '{
  "leagues": []
}' |
apify call lergassy/dfs-props-scraper --silent --output-dataset

```

## MCP server setup

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