UFCStats Scraper | Fight & Round Statistics
Pricing
from $0.86 / 1,000 results
UFCStats Scraper | Fight & Round Statistics
Export UFCStats MMA event or fight URLs as fighter-by-round rows with strikes, takedowns and source IDs. Include optional fight totals; keep errors outside the dataset.
Pricing
from $0.86 / 1,000 results
Rating
0.0
(0)
Developer
Eli J
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
20 hours ago
Last modified
Categories
Share
What you can export
Use this UFCStats scraper to export fight and round statistics from completed event cards or individual fight URLs. Each row identifies the fight, fighter and round; optional total rows retain the fight-level statistics separately.
Use round rows for round analysis and total rows for whole-fight analysis. Mixing their scopes double-counts the same underlying fight statistics.
How to export UFC fight and round statistics
- Copy an event URL from the UFCStats completed-events listing (see Input), or copy a fight URL, or use a bare 16-hex id.
- Put event cards in
eventUrlsand single fights infightUrls. - Choose
includeTotalsandmaxFights, and optionally setproxyConfiguration. - Start the run.
- Read the rows in the run's default dataset, and download them as CSV or
JSON. Failures and notices are in the run's
ERRORSrecord.
The public task Export UFC Paris 2026 fight and round statistics runs the example input shown under Input.
Pricing
How much does it cost to export UFC fight and round statistics?
A run is charged per dataset row plus the platform's automatic
apify-actor-start event, once per run at the default 512 MB of run memory. The
number of start events depends on the run's memory: one event per GB, with a
minimum of one event. A failure is never a dataset row, so it is never charged
as one, and the run's counters report the rows that actually landed. An input
that names no event and no fight writes no rows, so it incurs zero result-row
charges; the start event may still be charged for that run.
Per-fight row subtotals, before the start event: one fight's rows come to a
subtotal such as 4, 8 or 12 dataset rows. Each of those rows is charged at the
applicable row rate in the current Pricing section of this Actor's Apify Store
listing, and the automatic apify-actor-start event is charged separately, once
per run at the default 512 MB of run memory. These subtotals only illustrate how
one fight's rows add up; they are not a price for a card or a run.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
eventUrls | array | None; one card is prefilled in the Console | Event cards to take every fight from. An event-details URL in either host form, or a bare 16-hex event id. Up to 50 entries. |
fightUrls | array | None | Individual fights: a fight-details URL in either host form, or a bare 16-hex fight id. Up to 500 entries. Each one's event card is read once per event to join on the date and location. |
includeTotals | boolean | true | Adds one scope: "total" row per fight and fighter carrying that fight's own Totals and Significant Strikes cells. Turn it off to store and pay for per-round rows only. |
maxFights | integer | 50 | The ceiling on distinct fights one run reads, applied to the selection order below. Between 1 and 500. |
proxyConfiguration | object | Apify Proxy off | One proxy URL is resolved once per run and used for every request. If a run is refused, the Apify Proxy datacenter group is the first thing to try. |
Example input, the one the public task runs:
{"eventUrls": ["http://www.ufcstats.com/event-details/2144954270be834d"],"includeTotals": true,"maxFights": 50}
Copy event URLs from the UFCStats completed-events listing,
http://www.ufcstats.com/statistics/events/completed?page=all.
Targets are selected in eventUrls order, each card contributing its fights in
the card's own order, then fightUrls in order. The first occurrence of a fight
wins, so naming the same fight twice fetches it once, and a page is fetched only
when it will be processed.
A malformed input is reported by field name only: the run fails before any
request, and its ERRORS record names the field and the rule that failed, never
the value you sent, because an input field can carry a credential.
Requests per run
Every request to the source is counted before it is sent, requests go out one at a time at least 1.5 seconds apart, and nothing is retried.
- Conditional request arithmetic: a card listing 14 selected fights,
with no failures, requires
2 + 1 + 14 = 17requests: session, card and fight reads. This is an arithmetic example, not a new observation of the prefilled card's current contents. - The logical upper bound at the defaults, when a run mixes both arrays:
2 + 50 + 50 + 50 = 152requests -- 2 for the session, 50 named cards that contribute no selected fight, 50 further cards for 50 fights named directly whose cards all differ, and those 50 fights at the defaultmaxFightsof 50. - The hard ceiling, whatever the input: 1,052 requests. A run that reaches
it stops normally, and its
ERRORSrecord carries arequest-ceilingnotice naming the targets it left unfetched.
Output
One row per (fight, fighter, round) in the default dataset, recordType
fightRoundStats. A value the source does not carry is null; 0 means the
page printed a zero.
Totals rows repeat the round rows. With includeTotals on, each fighter
also gets one scope: "total" row per fight. If you sum the scope: "round"
rows and also keep the scope: "total" rows, you double count. Filter to
scope: "round" to add rows up, or read a scope: "total" row on its own.
Raw counts only. Every count is the page's own landed or attempted figure. The percentages the page prints are not emitted: they are yours to compute from these columns.
| Column | Type | Unit / form |
|---|---|---|
recordType | string | Literal fightRoundStats |
rowKey | string | <fightId>:<fighterId>:<scope>:<round-or-total>, unique within a fight |
fightId | string | 16 hex |
fightUrl | string | The absolute URL this run fetched |
eventId | string | 16 hex, read from the fight page's own event anchor |
eventName | string | As printed |
eventDate | string | null | YYYY-MM-DD, from the event card |
eventLocation | string | null | As printed, from the event card |
fighterId | string | 16 hex |
fighterName | string | As printed, trailing space stripped |
opponentId | string | 16 hex |
opponentName | string | As printed |
result | string | The page's own symbol (W, L), never coerced |
weightClass | string | As printed, Bout suffix kept |
method | string | As printed |
methodDetail | string | null | The raw joined Details: text |
endRound | integer | null | The round the fight ended in |
endTime | string | null | M:SS as printed |
timeFormat | string | null | As printed |
referee | string | null | As printed |
scope | string | round or total |
round | integer | null | 1-based; null on a total row |
knockdowns | integer | null | Count |
sigStrikesLanded | integer | null | Count |
sigStrikesAttempted | integer | null | Count |
totalStrikesLanded | integer | null | Count |
totalStrikesAttempted | integer | null | Count |
takedownsLanded | integer | null | Count |
takedownsAttempted | integer | null | Count |
submissionAttempts | integer | null | Count |
reversals | integer | null | Count |
controlTimeSeconds | integer | null | Seconds, converted from the page's M:SS |
headLanded | integer | null | Count |
headAttempted | integer | null | Count |
bodyLanded | integer | null | Count |
bodyAttempted | integer | null | Count |
legLanded | integer | null | Count |
legAttempted | integer | null | Count |
distanceLanded | integer | null | Count |
distanceAttempted | integer | null | Count |
clinchLanded | integer | null | Count |
clinchAttempted | integer | null | Count |
groundLanded | integer | null | Count |
groundAttempted | integer | null | Count |
scrapedAt | string | ISO-8601 UTC, stamped at fetch |
Every dataset row carries the 45 columns above. These field definitions describe the deployed output contract; actual values depend on the source.
When a target produces no rows
Failures are never dataset rows. Each one is recorded in the run's ERRORS
key-value record as an object with four keys -- target, id, errorClass,
message -- and the Actor's key-value store schema lists every class it can
carry, including the two run-level notices (charge-limit, request-ceiling)
that stop a run normally rather than failing it, and the no-stats note for a
fight whose page publishes no statistics tables at all.
Related Actors
| Actor | Research fit | What it exports |
|---|---|---|
| Kalshi Weather Markets | Price History API | Weather-market price history | Hourly or daily candles for named Kalshi weather markets: prices, bids, asks, volume and open interest as exact decimal strings |
| Tennis Abstract Scraper | Match History API | Tennis match statistics | ATP and WTA player match histories from Tennis Abstract: scores, opponents, surfaces and available serve and return statistics |
| Google Trends Scraper | Keyword Data API | Search-interest research | Google Trends interest over time, interest by region and related or rising queries, plus the Trending Now board by country |
| Clutch Agency Scraper | B2B Directory Export | Agency research and lead generation | B2B agency listings from Clutch.co directories: company names, websites, locations, headcounts and service mix |
| Google Ads Transparency Scraper & Archive | Ad-creative research | Advertiser ad records from Google's Ads Transparency Center: creative format, available images, first and last shown dates and source links |
FAQ and support
Why do my totals double count?
With includeTotals on, each fighter gets one scope: "total" row per fight
beside the round rows, so summing both counts every round twice. Filter to
scope: "round" to add rows up, read a scope: "total" row on its own, or turn
includeTotals off.
Are the round-by-round statistics counts or percentages?
Counts. Every count is the page's own landed or attempted figure; the
percentages the page prints are not emitted. A value the source does not carry
is null, and 0 means the page printed a zero.
Can one run export several cards or individual fights?
Yes. eventUrls takes up to 50 entries and fightUrls up to 500, and
maxFights caps the distinct fights one run reads. Cards are taken in
eventUrls order, then fights in fightUrls order; the first occurrence of a
fight wins, and a directly named fight's event card is read once per event. See
Requests per run for how requests add up.
What happens if the input names no event and no fight?
Nothing is fetched and no rows are written, so the run incurs zero result-row charges; the start event may still be charged for that run.
What happens when a page is refused or fails?
That target is written to the run's ERRORS record with its class, such as
blocked, not-found, unreadable-page or transport, and never as a dataset
row. Nothing is retried. If a run is refused, the Apify Proxy datacenter group
is the first thing to try; a proxy is not guaranteed to get a page through.
Source and terms
Public UFCStats pages, fetched over plain HTTP. This Actor reads no page behind a login, writes nothing back to the source, and emits professional athletes' and officials' competition statistics only.
Every UFCStats page footer links the UFC Terms of Use at https://ufc.com/terms. Those terms say they "apply to all Ultimate Fighting Championship® web sites" and to "all associated sites linked to" www.ufc.com by Zuffa, LLC; that you may not use any "deep-link", "page-scrape", "robot", "spider" or other automatic device to access the site; that commercial reproduction of the site or its information without Zuffa, LLC's prior written permission is not permitted; and that "these files may not be used to construct any kind of database". Whether ufcstats.com is one of those associated sites is an open question, and this Actor does not settle it. Disclosing the conflict does not cure it: you are responsible for your downstream use of the data.
For a question or a problem this page does not answer, open an issue on this Actor's Issues tab.