Football World Cup 2026
v1PublishedLive Polymarket odds for the 2026 FIFA World Cup Winner market: implied win probability, prices, volume, and liquidity for all 60 team markets.
›Author's sample data
| event | |
|---|---|
| teams |
›Publisher
1 subscriberEvery day at 2:00 AM1 runs in 14d · published 2h ago
›Versions
managed by authorv1builtapprovedcurrent2h ago
Schedulesdeploy to enable
Run this collector on a cadence — daily, hourly, your call.
API endpointdeploy to unlock
POST to run it on demand and get fresh data in the response.
Activitydeploy to track
1 subscriber runs in the last 14 days.
How this script collects data
import Firecrawl from "@mendable/firecrawl-js";
import * as cheerio from "cheerio";
const apiKey = process.env.FIRECRAWL_API_KEY;
if (!apiKey) {
console.error("FIRECRAWL_API_KEY is not set");
process.exit(1);
}
const firecrawl = new Firecrawl({ apiKey });
const EVENT_SLUG = "world-cup-winner";
const API_URL = `https://gamma-api.polymarket.com/events?slug=${EVENT_SLUG}`;
function extractJson(rawHtml: string): any {
// The gamma API returns plain JSON; depending on rendering it may arrive
// bare or wrapped in HTML (e.g. inside <pre>). Try bare first, then the
// text content of the page, then the outermost [...] span.
const candidates: string[] = [rawHtml];
try {
const $ = cheerio.load(rawHtml);
const pre = $("pre").text();
if (pre) candidates.push(pre);
candidates.push($("body").text() || $.root().text());
} catch {
// not HTML — bare candidate already covers it
}
for (const c of candidates) {
const trimmed = c.trim();
const start = trimmed.indexOf("[");
const end = trimmed.lastIndexOf("]");
if (start === -1 || end <= start) continue;
try {
return JSON.parse(trimmed.slice(start, end + 1));
} catch {
continue;
}
}
throw new Error("could not parse JSON from the Polymarket gamma API response");
}
function num(v: unknown): number | null {
if (v === null || v === undefined || v === "") return null;
const n = Number(v);
return Number.isFinite(n) ? n : null;
}
async function main() {
console.error(`Fetching Polymarket event: ${API_URL}`);
const doc = await firecrawl.scrape(API_URL, { formats: ["rawHtml"] });
const rawHtml = (doc as any).rawHtml ?? "";
if (!rawHtml) throw new Error("empty response from the Polymarket gamma API");
const events = extractJson(rawHtml);
if (!Array.isArray(events) || events.length === 0) {
throw new Error(`no Polymarket event found for slug "${EVENT_SLUG}"`);
}
const event = events[0];
const markets = event.markets;
if (!Array.isArray(markets) || markets.length === 0) {
throw new Error("event has no markets array in the gamma API response");
}
const teams = markets
.map((m: any) => {
let yesPrice: number | null = null;
try {
const prices = JSON.parse(m.outcomePrices ?? "[]");
yesPrice = num(prices[0]);
} catch {
yesPrice = null;
}
return {
team: (m.groupItemTitle || m.question || "").trim(),
impliedProbabilityPct:
yesPrice === null ? null : Math.round(yesPrice * 10000) / 100,
yesPrice,
bestBid: num(m.bestBid),
bestAsk: num(m.bestAsk),
lastTradePrice: num(m.lastTradePrice),
volumeUsd: num(m.volume),
liquidityUsd: num(m.liquidity),
eliminated: m.closed === true,
marketSlug: m.slug ?? null,
};
})
.filter((t: any) => t.team.length > 0)
.sort(
(a: any, b: any) =>
(b.yesPrice ?? -1) - (a.yesPrice ?? -1) ||
(b.volumeUsd ?? 0) - (a.volumeUsd ?? 0)
);
if (teams.length === 0) {
throw new Error("no team markets could be parsed from the event");
}
console.error(`Parsed ${teams.length} team markets`);
const out = {
event: {
title: (event.title ?? "").trim(),
slug: event.slug ?? EVENT_SLUG,
url: `https://polymarket.com/event/${event.slug ?? EVENT_SLUG}`,
endDate: event.endDate ?? null,
totalVolumeUsd: num(event.volume),
totalLiquidityUsd: num(event.liquidity),
teamCount: teams.length,
},
teams,
};
process.stdout.write(JSON.stringify(out));
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
Build prompt
Football World Cup 2026