Prometheus

Football World Cup 2026

v1Published

All 639 open FIFA World Cup 2026 events on Polymarket (9,217 markets) — tournament winner, group winners, every match, and props — with live odds, volume, and liquidity.

Author's sample data
events
sourcePolymarket (Gamma API)
eventCount639
tournamentFIFA World Cup 2026
marketCount9217
Publisher
0 subscribers
deam@deam
Every hour0 runs in 14d · published 3h ago
Versions
managed by author
v1builtapprovedcurrent3h 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

0 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 });

// Polymarket Gamma API tag id for "FIFA World Cup" (the 2026 tournament).
const TAG_ID = 102232;
const PAGE_SIZE = 100;
const MAX_PAGES = 50;

async function fetchPage(offset: number): Promise<any[]> {
  const url = `https://gamma-api.polymarket.com/events?tag_id=${TAG_ID}&closed=false&limit=${PAGE_SIZE}&offset=${offset}`;
  const res: any = await firecrawl.scrape(url, { formats: ["rawHtml"] });
  let raw: string = res?.rawHtml ?? "";
  if (raw.trimStart().startsWith("<")) {
    // Some renderers wrap JSON responses in an HTML page; recover the text.
    raw = cheerio.load(raw)("pre").text() || cheerio.load(raw)("body").text();
  }
  let parsed: any;
  try {
    parsed = JSON.parse(raw);
  } catch {
    throw new Error(`Gamma API response at offset ${offset} was not valid JSON`);
  }
  if (!Array.isArray(parsed)) {
    throw new Error(`Gamma API response at offset ${offset} was not an array of events`);
  }
  return parsed;
}

function parseJsonArray(s: unknown): any[] {
  if (typeof s !== "string") return [];
  try {
    const v = JSON.parse(s);
    return Array.isArray(v) ? v : [];
  } catch {
    return [];
  }
}

function toNumber(v: unknown): number | null {
  if (v === null || v === undefined || v === "") return null;
  const n = Number(v);
  return Number.isFinite(n) ? n : null;
}

function mapMarket(m: any) {
  const outcomeNames = parseJsonArray(m.outcomes);
  const outcomePrices = parseJsonArray(m.outcomePrices);
  const outcomes = outcomeNames.map((name: string, i: number) => ({
    name,
    price: toNumber(outcomePrices[i]),
  }));
  return {
    id: m.id ?? null,
    question: m.question ?? null,
    groupItemTitle: m.groupItemTitle || null,
    slug: m.slug ?? null,
    outcomes,
    volumeUsd: toNumber(m.volume),
    liquidityUsd: toNumber(m.liquidity),
    endDate: m.endDate ?? null,
    active: m.active ?? null,
    closed: m.closed ?? null,
  };
}

function mapEvent(e: any) {
  const title: string = e.title ?? "";
  const slug: string = e.slug ?? "";
  const isMatch = / vs\.? /i.test(title) || slug.startsWith("fifwc-");
  return {
    id: e.id ?? null,
    title: title.trim(),
    slug,
    url: slug ? `https://polymarket.com/event/${slug}` : null,
    category: isMatch ? "match" : "futures-and-props",
    description: e.description ?? null,
    startDate: e.startDate ?? null,
    endDate: e.endDate ?? null,
    volumeUsd: toNumber(e.volume),
    liquidityUsd: toNumber(e.liquidity),
    commentCount: e.commentCount ?? null,
    markets: Array.isArray(e.markets) ? e.markets.map(mapMarket) : [],
  };
}

async function main() {
  const events: any[] = [];
  const seen = new Set<string>();
  for (let page = 0; page < MAX_PAGES; page++) {
    const offset = page * PAGE_SIZE;
    console.error(`Fetching events at offset ${offset}...`);
    const batch = await fetchPage(offset);
    for (const e of batch) {
      const id = String(e.id ?? e.slug ?? "");
      if (id && seen.has(id)) continue;
      if (id) seen.add(id);
      events.push(mapEvent(e));
    }
    if (batch.length < PAGE_SIZE) break;
  }
  if (events.length === 0) {
    throw new Error("no open FIFA World Cup events returned by the Gamma API");
  }
  events.sort((a, b) => (b.volumeUsd ?? 0) - (a.volumeUsd ?? 0));
  const marketCount = events.reduce((n, e) => n + e.markets.length, 0);
  console.error(`Collected ${events.length} events with ${marketCount} markets.`);
  const out = {
    tournament: "FIFA World Cup 2026",
    source: "Polymarket (Gamma API)",
    eventCount: events.length,
    marketCount,
    events,
  };
  process.stdout.write(JSON.stringify(out));
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
Build prompt
Football World Cup 2026
One person builds it. Everyone keeps it fresh.