{"id":3723,"date":"2026-08-30T10:00:00","date_gmt":"2026-08-30T10:00:00","guid":{"rendered":"https:\/\/oddspapi.io\/blog\/?p=3723"},"modified":"2026-08-29T15:05:10","modified_gmt":"2026-08-29T15:05:10","slug":"college-football-player-props-api","status":"publish","type":"post","link":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/","title":{"rendered":"College Football Player Props API: 22 Markets Across 63 Books"},"content":{"rendered":"<p>Three weeks ago the college football board had <strong>zero player props<\/strong>. Not a thin menu \u2014 none, across 112 distinct market IDs.<\/p>\n<p>They arrived for Week 1. The current NCAA slate carries <strong>21,627 player-keyed prices across 22 prop families and 63 bookmakers<\/strong>, from receiving yards ladders to first touchdown scorer. This post shows how to pull them, and the two things that will make your parser return an empty dict if you get them wrong.<\/p>\n<h2>The trap: props are not keyed like game lines<\/h2>\n<p>Every OddsPapi price sits under a <code>players<\/code> dict. On a moneyline or a spread, that dict has exactly one key, the string <code>\"0\"<\/code>. Every tutorial you have read hardcodes it.<\/p>\n<p><strong>On a player prop, <code>players<\/code> is keyed by player ID instead<\/strong>, and one outcome holds the entire roster at once. &#8220;Over 49.5 receiving yards&#8221; is a single outcome containing every receiver the book prices, each with its own <code>price<\/code> and a <code>playerName<\/code> in <code>\"Last, First\"<\/code> format.<\/p>\n<p>So <code>outcome[\"players\"][\"0\"]<\/code> raises a <code>KeyError<\/code> or returns nothing on every prop market on the board.<\/p>\n<pre class=\"wp-block-code\"><code>import requests, time, collections\n\nAPI_KEY  = \"YOUR_API_KEY\"\nBASE_URL = \"https:\/\/api.oddspapi.io\/v4\"\n\ndef get(path, **params):\n    for _ in range(5):\n        params[\"apiKey\"] = API_KEY\n        r = requests.get(f\"{BASE_URL}\/{path}\", params=params)\n        if r.status_code == 429:\n            time.sleep(r.json()[\"error\"].get(\"retryMs\", 1500) \/ 1000 + 1.2)\n            continue\n        return r.status_code, r.json()\n    return r.status_code, {}\n\ndef player_prices(outcome):\n    \"\"\"Yield every player-level price on an outcome. Skips the game-line key.\"\"\"\n    for player_id, price in outcome[\"players\"].items():\n        if player_id == \"0\":          # \"0\" == not a player prop\n            continue\n        yield player_id, price\n<\/code><\/pre>\n<h2>Step 1: build the market lookup<\/h2>\n<p>Market IDs are integers and human-readable names come from <code>\/v4\/markets<\/code>. Two things to know before you use it.<\/p>\n<p><strong><code>sportId<\/code> on that endpoint is a no-op.<\/strong> The catalogue is global \u2014 32,815 rows \u2014 not per sport, so you cannot use it to discover which markets college football supports. Read the live market IDs off the <code>\/odds<\/code> payload and use the catalogue purely as a lookup.<\/p>\n<p><strong>American football uses one market ID per line.<\/strong> The receiving-yards family alone spans <strong>88 distinct market IDs<\/strong> on a single slate, one per yardage threshold. Never hardcode them; resolve by <code>marketName<\/code>.<\/p>\n<pre class=\"wp-block-code\"><code>status, catalogue = get(\"markets\", sportId=14)\n\nMARKET = {m[\"marketId\"]: (m[\"marketName\"], m.get(\"handicap\")) for m in catalogue}\nOUTCOME = {(m[\"marketId\"], o[\"outcomeId\"]): o[\"outcomeName\"]\n           for m in catalogue for o in m.get(\"outcomes\", [])}\n<\/code><\/pre>\n<h2>Step 2: pull a fixture and collect the props<\/h2>\n<p>NCAA regular season is <code>tournamentId<\/code> 27653 under <code>sportId<\/code> 14. Coverage is extremely uneven \u2014 many small-college fixtures return no bookmakers at all \u2014 so pick a fixture with a real board before you go looking for props.<\/p>\n<pre class=\"wp-block-code\"><code>def props(fixture_id):\n    status, odds = get(\"odds\", fixtureId=fixture_id)\n    rows = []\n    for slug, book in odds.get(\"bookmakerOdds\", {}).items():\n        if slug.startswith(\"pinnacle+\") or slug == \"demo\":     # internal test feeds\n            continue\n        for market_id, market in book.get(\"markets\", {}).items():\n            family, handicap = MARKET.get(int(market_id), (\"?\", None))\n            for outcome_id, outcome in market[\"outcomes\"].items():\n                label = OUTCOME.get((int(market_id), int(outcome_id)))\n                for player_id, price in player_prices(outcome):\n                    rows.append({\n                        \"book\": slug, \"family\": family, \"handicap\": handicap,\n                        \"label\": label, \"player_id\": player_id,\n                        \"player\": price.get(\"playerName\"),\n                        \"price\": price.get(\"price\"),\n                        \"active\": price.get(\"active\"),\n                    })\n    return rows\n\nrows = props(\"id1402765370894628\")     # North Carolina @ TCU\nprint(len(rows), \"player-level prices from\",\n      len({r[\"book\"] for r in rows}), \"books\")\n# 6163 player-level prices from 60 books\n<\/code><\/pre>\n<p>That one fixture returns <strong>6,163 player-level prices from 60 bookmakers<\/strong>. Across the four most prop-heavy fixtures of the slate it comes to <strong>16,599 prices from 63 books<\/strong>.<\/p>\n<h2>What is actually on the board<\/h2>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Prop family<\/th>\n<th>Prices<\/th>\n<th>Active<\/th>\n<th>Books<\/th>\n<th>Players<\/th>\n<th>Market IDs<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Over Under Player Receiving Yards<\/td>\n<td>7,366<\/td>\n<td>40.2%<\/td>\n<td><strong>55<\/strong><\/td>\n<td>19<\/td>\n<td>88<\/td>\n<\/tr>\n<tr>\n<td>Over Under Rush Yards<\/td>\n<td>2,315<\/td>\n<td>30.0%<\/td>\n<td>26<\/td>\n<td>15<\/td>\n<td>78<\/td>\n<\/tr>\n<tr>\n<td>Player To Score TD<\/td>\n<td>1,565<\/td>\n<td><strong>97.4%<\/strong><\/td>\n<td>20<\/td>\n<td>103<\/td>\n<td>2<\/td>\n<\/tr>\n<tr>\n<td>Over Under Pass Yards<\/td>\n<td>1,354<\/td>\n<td><strong>16.0%<\/strong><\/td>\n<td>51<\/td>\n<td>3<\/td>\n<td>57<\/td>\n<\/tr>\n<tr>\n<td>Rush Yards (alt ladder)<\/td>\n<td>1,311<\/td>\n<td>98.6%<\/td>\n<td>38<\/td>\n<td>9<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td>Player To Score First TD<\/td>\n<td>807<\/td>\n<td>93.1%<\/td>\n<td>23<\/td>\n<td>102<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td>Over Under Player Receptions<\/td>\n<td>381<\/td>\n<td>89.2%<\/td>\n<td>34<\/td>\n<td>75<\/td>\n<td>8<\/td>\n<\/tr>\n<tr>\n<td>Over Under Longest Rush Yards<\/td>\n<td>370<\/td>\n<td>65.9%<\/td>\n<td>10<\/td>\n<td>30<\/td>\n<td>17<\/td>\n<\/tr>\n<tr>\n<td>Over Under Player TD Passes<\/td>\n<td>170<\/td>\n<td>87.1%<\/td>\n<td>24<\/td>\n<td>12<\/td>\n<td>3<\/td>\n<\/tr>\n<tr>\n<td>Over Under Player Assists<\/td>\n<td>289<\/td>\n<td>99.3%<\/td>\n<td><strong>1<\/strong><\/td>\n<td>146<\/td>\n<td>4<\/td>\n<\/tr>\n<tr>\n<td>Over Under Sacks<\/td>\n<td>185<\/td>\n<td>98.9%<\/td>\n<td><strong>1<\/strong><\/td>\n<td>146<\/td>\n<td>1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>Twenty-two families in total, down a long tail that includes rush attempts, pass completions, interceptions, longest pass completion and kicking points.<\/p>\n<h2>The active rate varies 6x between families<\/h2>\n<p>This is the finding that matters most for anything automated. Across those 16,599 prices only <strong>54.8% are active<\/strong>, and the split is not random:<\/p>\n<ul>\n<li><strong>Touchdown-scorer markets are live.<\/strong> Player To Score TD 97.4%, First TD 93.1%. These are single-market families with one line and no ladder.<\/li>\n<li><strong>Yardage ladders are mostly switched off.<\/strong> Pass Yards 16.0%, Rush Yards 30.0%, Receiving Yards 40.2%. These are the families with 57 to 88 market IDs each \u2014 a book posts the whole ladder and keeps a handful of rungs open.<\/li>\n<\/ul>\n<p>So a scanner that skips the <code>active<\/code> filter sees a receiving-yards market that looks 2.5 times deeper than it is, and one that filters correctly finds most of the ladder is dead. Both are worth knowing before you build an alerting rule on top.<\/p>\n<pre class=\"wp-block-code\"><code>live = [r for r in rows if r[\"active\"]]\nby_family = collections.Counter(r[\"family\"] for r in live)\nprint(len(rows), \"prices ->\", len(live), \"active\")\n\nfor family, n in by_family.most_common(10):\n    total = sum(1 for r in rows if r[\"family\"] == family)\n    print(f\"{family[:44]:<46} {n:>5} live \/ {total:>5}  ({100*n\/total:.1f}%)\")\n<\/code><\/pre>\n<p>Note the flag you filter on. <code>active<\/code> lives on the price object, one level below the outcome. <code>marketActive<\/code>, <code>suspended<\/code> and <code>bookmakerIsActive<\/code> all exist and all disagree with their own prices often enough to break a parser.<\/p>\n<h2>Dedupe before you compare anything<\/h2>\n<p>The top prop books by volume look like a diverse field and are not:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Book<\/th>\n<th>Prop prices<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>stake<\/code><\/td>\n<td>1,450<\/td>\n<\/tr>\n<tr>\n<td><code>bet365<\/code><\/td>\n<td>774<\/td>\n<\/tr>\n<tr>\n<td><code>bet365.bet.ar<\/code>, <code>.bet.br<\/code>, <code>.de<\/code>, <code>.es<\/code>, <code>.fr<\/code>, <code>.gr<\/code>, <code>.it<\/code>, <code>.nl<\/code><\/td>\n<td>774 each<\/td>\n<\/tr>\n<tr>\n<td><code>fliff<\/code><\/td>\n<td>568<\/td>\n<\/tr>\n<tr>\n<td><code>betsson<\/code><\/td>\n<td>470<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p><strong>bet365 and its seven regional skins ship byte-identical prop books.<\/strong> Counting them as eight sources inflates any consensus you build by a factor of eight on the biggest prop provider on the board. All of them report <code>cloneOf: null<\/code> in the catalogue, so the flag will not save you \u2014 dedupe on the price tuple, per fixture.<\/p>\n<p>The scale of it is easy to underestimate. On the TCU game&#8217;s receiving-yards market, <strong>53 books collapse to 17 independent prop books, a 68% collapse.<\/strong> Two thirds of your apparent sample is one feed wearing several brands.<\/p>\n<pre class=\"wp-block-code\"><code>def independent(rows, family):\n    \"\"\"Collapse books that ship identical prop books for one family.\"\"\"\n    signature = collections.defaultdict(dict)\n    for r in rows:\n        if r[\"family\"] == family and r[\"active\"]:\n            signature[r[\"book\"]][(r[\"player_id\"], r[\"handicap\"], r[\"label\"])] = r[\"price\"]\n    seen, keep = set(), []\n    for book, prices in signature.items():\n        key = tuple(sorted(prices.items()))\n        if key not in seen:\n            seen.add(key)\n            keep.append(book)\n    return keep\n<\/code><\/pre>\n<h2>Reading a yardage ladder<\/h2>\n<p>Yardage props ship as threshold ladders rather than a single line. Outcome names are the thresholds themselves \u2014 <code>3+<\/code>, <code>60+<\/code>, <code>70+<\/code>, <code>90+<\/code>, <code>110+<\/code>, <code>400+<\/code> \u2014 alongside plain <code>Over<\/code> and <code>Under<\/code> for the two-sided variants.<\/p>\n<p>That means two different shapes live under names that look similar. <code>Over Under Player Receiving Yards<\/code> is a two-sided market with a handicap; <code>Rush Yards<\/code> is a one-sided threshold ladder on a single market ID. Only the first can be de-vigged, because only the first has two legs.<\/p>\n<pre class=\"wp-block-code\"><code>def two_sided(rows):\n    \"\"\"Group into (book, player, handicap) and keep only real pairs.\"\"\"\n    groups = collections.defaultdict(dict)\n    for r in rows:\n        if r[\"active\"] and r[\"handicap\"] is not None:\n            groups[(r[\"book\"], r[\"player_id\"], r[\"handicap\"])][r[\"label\"]] = r[\"price\"]\n    return {k: v for k, v in groups.items()\n            if \"Over\" in v and \"Under\" in v}\n\npairs = two_sided([r for r in rows\n                   if r[\"family\"] == \"Over Under Player Receiving Yards (incl. overtime)\"])\nfor (book, player, line), legs in list(pairs.items())[:5]:\n    margin = (1 \/ legs[\"Over\"] + 1 \/ legs[\"Under\"] - 1) * 100\n    print(f\"{book:<16} player {player} @ {line:>6}  margin {margin:5.2f}%\")\n<\/code><\/pre>\n<h2>Two honest limits<\/h2>\n<p><strong>Coverage is thin and concentrated.<\/strong> Props exist on the marquee fixtures and nowhere else. Across the whole 136-game NCAA Week 1 slate there are 21,627 player-keyed prices, and roughly three quarters of them sit on four games. On a small-college fixture there is no board at all, let alone props.<\/p>\n<p><strong>Two families come from a single book.<\/strong> Over Under Player Assists and Over Under Sacks each have 146 players priced by exactly one bookmaker. One source is not a market: there is nothing to check the number against, so treat those two as reference data rather than as a price you can screen.<\/p>\n<p>The same caution applies to Pass Yards, where 51 books quote the family but only <strong>three players<\/strong> are priced across it \u2014 the quarterbacks, and almost every rung suspended.<\/p>\n<h2>Old way vs OddsPapi<\/h2>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th>Scraping sportsbooks<\/th>\n<th>OddsPapi<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Prop coverage<\/td>\n<td>One scraper per book, breaks weekly<\/td>\n<td>63 books with props in one JSON call<\/td>\n<\/tr>\n<tr>\n<td>Player identity<\/td>\n<td>Free-text names to reconcile<\/td>\n<td>Stable player IDs plus <code>playerName<\/code><\/td>\n<\/tr>\n<tr>\n<td>Suspended rungs<\/td>\n<td>Rendered like live ones<\/td>\n<td>Explicit <code>active<\/code> flag per price<\/td>\n<\/tr>\n<tr>\n<td>Market naming<\/td>\n<td>Different per book<\/td>\n<td>One <code>marketName<\/code> across the board<\/td>\n<\/tr>\n<tr>\n<td>Cost<\/td>\n<td>Proxies and maintenance<\/td>\n<td>Free tier<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>Where to go next<\/h2>\n<ul>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/college-football-odds-coverage\/\">College football odds coverage<\/a> \u2014 which of the 136 Week 1 games have a board at all, and how to tell before you call.<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/college-football-odds-api\/\">College football odds API<\/a> \u2014 lines, spreads and totals for NCAAF.<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/player-props-api-nfl-nba-mlb-odds-python\/\">Player props API for NFL, NBA and MLB<\/a> \u2014 the same parsing pattern on the pro leagues.<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/player-props-value-scanner-python\/\">Player props value scanner<\/a> \u2014 finding outliers once you have the board.<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/nfl-alternate-lines-api\/\">NFL alternate lines API<\/a> \u2014 why ladder markets suspend the way they do.<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/mlb-player-props-api\/\">MLB player props API<\/a> \u2014 home runs, strikeouts and hits.<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/vig-calculator-python-sportsbook-margin\/\">Vig calculator in Python<\/a> \u2014 the margin maths for two-sided props.<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/consensus-odds-fair-odds-calculator-python\/\">Consensus odds<\/a> \u2014 what to do after you dedupe.<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/line-shopping-python-best-odds\/\">Line shopping in Python<\/a> \u2014 best price per player across the board.<\/li>\n<li><a href=\"https:\/\/oddspapi.io\/blog\/free-odds-api-350-bookmakers\/\">Free odds API<\/a> \u2014 the tier all of this runs on.<\/li>\n<\/ul>\n<h2>Props exist now. Parse them properly.<\/h2>\n<p>College player props went from nothing to 22 families in three weeks, and the two things that break a prop parser \u2014 the player-keyed <code>players<\/code> dict and the suspended half of every yardage ladder \u2014 are both one line of code each. The board is 350+ bookmakers including Pinnacle, bet365, DraftKings and Kalshi, with free historical odds behind every fixture.<\/p>\n<p><strong><a href=\"https:\/\/oddspapi.io\/\">Get your free API key<\/a><\/strong> and pull this weekend&#8217;s prop board.<\/p>\n<p><script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How do I get college football player props from an API?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Call OddsPapi's \/odds endpoint with an NCAA fixtureId, then iterate the players dict on each outcome. On player props that dict is keyed by player ID rather than the string \\\"0\\\" used by game lines, and each entry carries a playerName in Last, First format. The current NCAA slate carries 21,627 player-keyed prices across 22 prop families and 63 bookmakers.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Why does my player prop parser return nothing?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Almost always because it hardcodes outcome[\\\"players\\\"][\\\"0\\\"]. That key only exists on game lines such as moneylines, spreads and totals. Player props key the same dict by player ID, so one outcome holds the whole roster. Iterate the dict and skip the \\\"0\\\" key instead.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Which college football player props have the most bookmakers?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Over Under Player Receiving Yards leads with 55 bookmakers across 88 market IDs, followed by Over Under Pass Yards on 51 books and Rush Yards on 38. Touchdown scorer markets are narrower, with Player To Score TD on 20 books, but they price far more players, 103 against 19 for receiving yards.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Why are so many player prop prices inactive?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Books post a full yardage ladder and keep only a few rungs open. Across 16,599 college prop prices 54.8% were active, but the rate varies sharply by family: Player To Score TD ran 97.4% active while Over Under Pass Yards ran 16.0%. Filter on the price-level active flag rather than marketActive or suspended.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Do bet365 regional sites count as separate prop sources?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"No. bet365 and seven regional skins including bet365.de, bet365.es and bet365.it ship byte-identical prop books, 774 prices each, and all report cloneOf: null in the catalogue. Counting them separately inflates a consensus eightfold on the largest prop provider on the board. Dedupe on the price tuple per fixture.\"\n      }\n    }\n  ]\n}\n<\/script><\/p>\n<p><!--\nFocus Keyphrase: college football player props api\nSEO Title: College Football Player Props API: 22 Markets in Python\nMeta Description: College player props went from zero to 22 families in three weeks. Pull all 63 bookmakers in Python - and avoid the players[\"0\"] bug that returns an empty dict.\nSlug: college-football-player-props-api\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>College player props went from zero to 22 families in three weeks. Pull all 63 bookmakers in Python, and avoid the players[0] bug that returns an empty dict.<\/p>\n","protected":false},"author":2,"featured_media":3726,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[81,8,9,51,11],"class_list":["post-3723","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to-guides","tag-college-football","tag-free-api","tag-odds-api","tag-player-props","tag-python"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>College Football Player Props API: 22 Markets Across 63 Books | OddsPapi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"College Football Player Props API: 22 Markets Across 63 Books | OddsPapi Blog\" \/>\n<meta property=\"og:description\" content=\"College player props went from zero to 22 families in three weeks. Pull all 63 bookmakers in Python, and avoid the players[0] bug that returns an empty dict.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/\" \/>\n<meta property=\"og:site_name\" content=\"OddsPapi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-30T10:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1429\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Odds API Writer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/oddspapi.io\/logo-v2.webp\" \/>\n<meta name=\"twitter:creator\" content=\"@oddspapiapi\" \/>\n<meta name=\"twitter:site\" content=\"@oddspapiapi\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Odds API Writer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/\"},\"author\":{\"name\":\"Odds API Writer\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\"},\"headline\":\"College Football Player Props API: 22 Markets Across 63 Books\",\"datePublished\":\"2026-08-30T10:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/\"},\"wordCount\":1124,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp\",\"keywords\":[\"College Football\",\"Free API\",\"Odds API\",\"Player Props\",\"Python\"],\"articleSection\":[\"How To Guides\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/\",\"name\":\"College Football Player Props API: 22 Markets Across 63 Books | OddsPapi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp\",\"datePublished\":\"2026-08-30T10:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#primaryimage\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp\",\"width\":2560,\"height\":1429,\"caption\":\"College Player Props - OddsPapi API Blog\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/oddspapi.io\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"College Football Player Props API: 22 Markets Across 63 Books\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\",\"url\":\"https:\/\/oddspapi.io\/blog\/\",\"name\":\"OddsPapi\",\"description\":\"Sports Odds API Tutorials &amp; Guides\",\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"alternateName\":\"Odds Papi\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/oddspapi.io\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\",\"name\":\"OddsPapi\",\"url\":\"https:\/\/oddspapi.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png\",\"width\":135,\"height\":135,\"caption\":\"OddsPapi\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/oddspapiapi\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\",\"name\":\"Odds API Writer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g\",\"caption\":\"Odds API Writer\"},\"url\":\"https:\/\/oddspapi.io\/blog\/author\/andy-lavelle\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"College Football Player Props API: 22 Markets Across 63 Books | OddsPapi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/","og_locale":"en_US","og_type":"article","og_title":"College Football Player Props API: 22 Markets Across 63 Books | OddsPapi Blog","og_description":"College player props went from zero to 22 families in three weeks. Pull all 63 bookmakers in Python, and avoid the players[0] bug that returns an empty dict.","og_url":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/","og_site_name":"OddsPapi Blog","article_published_time":"2026-08-30T10:00:00+00:00","og_image":[{"width":2560,"height":1429,"url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp","type":"image\/webp"}],"author":"Odds API Writer","twitter_card":"summary_large_image","twitter_image":"https:\/\/oddspapi.io\/logo-v2.webp","twitter_creator":"@oddspapiapi","twitter_site":"@oddspapiapi","twitter_misc":{"Written by":"Odds API Writer","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#article","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/"},"author":{"name":"Odds API Writer","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13"},"headline":"College Football Player Props API: 22 Markets Across 63 Books","datePublished":"2026-08-30T10:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/"},"wordCount":1124,"commentCount":0,"publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp","keywords":["College Football","Free API","Odds API","Player Props","Python"],"articleSection":["How To Guides"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/","url":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/","name":"College Football Player Props API: 22 Markets Across 63 Books | OddsPapi Blog","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#primaryimage"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp","datePublished":"2026-08-30T10:00:00+00:00","breadcrumb":{"@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#primaryimage","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/college-football-player-props-api-scaled.webp","width":2560,"height":1429,"caption":"College Player Props - OddsPapi API Blog"},{"@type":"BreadcrumbList","@id":"https:\/\/oddspapi.io\/blog\/college-football-player-props-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/oddspapi.io\/blog\/"},{"@type":"ListItem","position":2,"name":"College Football Player Props API: 22 Markets Across 63 Books"}]},{"@type":"WebSite","@id":"https:\/\/oddspapi.io\/blog\/#website","url":"https:\/\/oddspapi.io\/blog\/","name":"OddsPapi","description":"Sports Odds API Tutorials &amp; Guides","publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"alternateName":"Odds Papi","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/oddspapi.io\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/oddspapi.io\/blog\/#organization","name":"OddsPapi","url":"https:\/\/oddspapi.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png","width":135,"height":135,"caption":"OddsPapi"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/oddspapiapi"]},{"@type":"Person","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13","name":"Odds API Writer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g","caption":"Odds API Writer"},"url":"https:\/\/oddspapi.io\/blog\/author\/andy-lavelle\/"}]}},"_links":{"self":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/comments?post=3723"}],"version-history":[{"count":3,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3723\/revisions"}],"predecessor-version":[{"id":3870,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3723\/revisions\/3870"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media\/3726"}],"wp:attachment":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media?parent=3723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/categories?post=3723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/tags?post=3723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}