# Sherdog Fight History - MMA Fighter Records & Event Cards (`neverempty/sherdog-fight-history`) Actor

MMA fighter records and full event cards from Sherdog: wins, losses, draws and no contests, every pro fight with opponent, result, method, round, time, date and event, plus height, weight, gym and nationality. UFC, PFL, Bellator, ONE, Rizin or any promotion. Monitoring returns only new fights.

- **URL**: https://apify.com/neverempty/sherdog-fight-history.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Sports, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $18.00 / 1,000 record returneds

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Sherdog Fight History - MMA fighter records, fight results, event cards

**For MMA analytics, betting models, fight previews and fighter scouting**: fighter records and full fight cards from **sherdog.com**, the largest public MMA record database - UFC, PFL, Bellator, ONE, Rizin and any other promotion Sherdog lists.

**Give it a fighter, an event or a promotion.** A fighter URL or just a name returns that fighter's whole pro record - every fight with opponent, result, method, round, time, date and event - plus height, weight, gym and nationality, **in one row**. An event URL returns the full card, bout by bout. A promotion returns its newest cards.

**Built for a schedule.** Turn on monitoring and each run returns only fighters with a new fight on their record, new bouts, and bouts whose result has just been filled in - nothing you already have, nothing charged twice.

No API key, no login. Export as JSON, CSV or Excel.

### What you get

#### Fights (default)

One row per bout on the card, with:

- **The card**: event name, date, location, organization, weight class, title fight or not, the bout's place on the card and whether it is the main event
- **Both fighters**: name, Sherdog id and their result written out (`win`, `loss`, `draw`, `no contest`)
- **The finish**: method (`KO`, `TKO`, `Submission`, `Decision`, …), the detail (`Rear-Naked Choke`, `Unanimous`), the round, the time (also in seconds) and the referee
- **The winner** by name and id, with `isDraw` and `isNoContest` set from the result itself
- **Links**: `eventUrl` is the event's Sherdog page, and `url` is that page plus the bout's place on the card (`#match-12`), one per bout

#### Fighters

One row per fighter, with:

- **The record**: wins, losses, draws and no contests, and the record as Sherdog prints it (`28-1-0 (1 NC)`)
- **How they win and lose**: wins and losses by KO/TKO, submission, decision and other
- **The profile**: nickname, height (as printed and in inches), weight in pounds, gym (association), nationality, hometown, date of birth, weight class
- **The full history** in a `fights` array: opponent and their id, result, method and detail, round, time, date, event and referee - plus amateur fights in their own array
- **What is next**: the next booked fight, and the date of the last one

#### Events

One row per event: name, date, location, organization, and whether it has happened, is still upcoming or was canceled.

***

### Example output (one fight)

```json
{
  "recordType": "fight",
  "eventName": "UFC 309 - Jones vs. Miocic",
  "eventDate": "2024-11-16",
  "location": "Madison Square Garden, New York, New York, United States",
  "weightClass": "Heavyweight",
  "isTitleFight": true,
  "fighter1": "Jon Jones",    "fighter1Id": "27944", "fighter1Result": "win",
  "fighter2": "Stipe Miocic", "fighter2Id": "39537", "fighter2Result": "loss",
  "winner": "Jon Jones",
  "method": "TKO",
  "methodDetail": "Spinning Back Kick and Punches",
  "endRound": 3, "endTime": "4:29", "endTimeSeconds": 269,
  "referee": "Herb Dean",
  "isMainEvent": true,
  "hasResult": true
}
```

### Example output (one fighter, history shortened)

```json
{
  "recordType": "fighter",
  "name": "Jon Jones", "nickname": "Bones", "fighterId": "27944",
  "recordText": "28-1-0 (1 NC)", "wins": 28, "losses": 1, "draws": 0, "noContests": 1,
  "winsByKo": 11, "winsBySubmission": 7, "winsByDecision": 10,
  "heightText": "6'4\"", "heightInches": 76, "weightPounds": 238,
  "association": "Jackson-Wink MMA",
  "nationality": "United States",
  "dateOfBirth": "1987-07-19",
  "lastFightDate": "2024-11-16",
  "fightsListed": 30,
  "fights": [
    { "result": "win", "opponent": "Stipe Miocic", "event": "UFC 309 - Jones vs. Miocic", "eventDate": "2024-11-16",
      "method": "TKO", "methodDetail": "Spinning Back Kick and Punches", "round": 3, "time": "4:29" },
    { "result": "win", "opponent": "Ciryl Gane", "event": "UFC 285 - Jones vs. Gane", "eventDate": "2023-03-04",
      "method": "Submission", "methodDetail": "Guillotine Choke", "round": 1, "time": "2:04" }
  ]
}
```

***

### Input

| Field | Key | What it does |
|---|---|---|
| **What to collect** | `mode` | `fights` (default), `events` or `fighters` |
| **Organizations** | `organizations` | `UFC`, `PFL`, `Bellator`, `ONE`, `Rizin` by name, or any promotion's Sherdog URL. Its newest events are read |
| **How many events per organization** | `maxEvents` | Events are read newest first; a big card holds roughly 10-15 bouts. In `fighters` mode, every fighter on these cards is read |
| **Sherdog URLs** | `startUrls` | Fighter, event or organization pages. Event URLs give the full card; fighter URLs give the record |
| **Fighter names** | `fighterNames` | In `fighters` mode: look fighters up by name. In the other modes: keep only bouts with these fighters |
| **Include upcoming events** | `includeUpcoming` | Off by default. On: announced cards come first, with result columns that fill in after the event |
| **Maximum records** | `maxRecords` | The most rows this run may return and charge for |
| **Weight classes** | `weightClasses` | Keep only records in these weight classes; case-insensitive and partial |
| **Keywords / match / exclude** | `keywords`, `keywordMatch`, `excludeKeywords` | Text filters over event, bout, fighter names, location, method, gym and nationality |
| **Only return what changed** | `monitoringMode` | For a schedule, see below |
| **Forget what was returned** | `resetMonitoringState` | Clears that memory once |
| **Maximum requests** | `maxRequests` | A hard ceiling on how many pages this run reads |
| **Use an Apify proxy** | `useProxy` | Off by default; turn on only if pages fail to load |

#### Ready-made inputs

**One fighter's record, by name:**

```json
{ "mode": "fighters", "fighterNames": ["Alexander Volkanovski"] }
```

**The full card of one event:**

```json
{ "startUrls": [{ "url": "https://www.sherdog.com/events/UFC-309-Jones-vs-Miocic-103896" }] }
```

**The latest PFL and Bellator results:**

```json
{ "organizations": ["PFL", "Bellator"], "maxEvents": 2 }
```

**Watch a roster for new fights (schedule this daily):**

```json
{ "mode": "fighters", "fighterNames": ["Jon Jones", "Tom Aspinall"], "monitoringMode": true }
```

***

### Monitoring: only what changed

With **Only return what changed since the last run** on, the Actor remembers what it returned:

- **Fighters mode**: a fighter comes back only when a new fight appears on their record.
- **Fights mode**: new bouts come back, and so does a bout announced earlier **once its result is filled in** - so you can watch an upcoming card and get each result the day after.
- **Events mode**: new events come back, and an upcoming event comes back again once it has taken place.

Each state is charged once. A run with nothing new returns one free row that says so. Different inputs (another organization, other filters) keep separate memories, and the order or capital letters of your filters do not matter.

***

### Things this Actor is careful about

**The right fighter, or a clear "no".** A Sherdog address with a mistyped id can open a different fighter's page - `Jon-Jones-27945` opens someone else entirely. This Actor checks that the page it got is the fighter, event or promotion you asked for. If not, you get a free row saying so, never another person's record under the name you asked for.

**Names that match several people.** Searching for a common name like *Michael Johnson* finds several real fighters. The Actor returns each of them, and a free row lists every match with its Sherdog URL, so you can keep the one you mean and use that URL next time. A name that matches nobody returns a free row with the nearest names Sherdog found.

**Upcoming and canceled cards are labelled.** An announced card has `hasResult: false` and empty result columns until the fights happen. A canceled event is marked `isCanceled: true` and is never passed off as a finished card.

**Empty is not zero.** When Sherdog has no value - no date of birth, no time for a bout - the field is `null`, never `0`.

**"Could not read" is never reported as "no data".** A page that fails, a page that does not exist, a filter that matched nothing, a result cut short by your maximum - each comes back as its own labelled row with the URL, and none of them is charged.

**The limit does not delete whole events.** When *Maximum records* cuts the result, rows are taken evenly from every event, and a free row tells you how many were left out.

### Good to know

- Pages are read one at a time with a short pause, the way a person would browse. A typical card takes well under a minute; `fighters` mode on several full cards reads one page per fighter and takes longer.
- Sherdog publishes results and records, not strike counts. For significant strikes, takedowns and control time, use a statistics source alongside this data.
- Searching by name looks for the exact name (accents and capital letters ignored). For a fighter with a very common name, use their Sherdog URL.
- Hometown, gym and date of birth are as Sherdog lists them; some older or regional fighters have them blank.

***

### Frequently asked

**How do I get a fighter's full fight history from Sherdog?** Set *What to collect* to `fighters` and give the fighter's name or Sherdog URL. You get one row with the record, height, weight, gym, nationality and every pro fight with opponent, result, method, round, time, date and event.

**How do I get the full card of an MMA event?** Paste the event's Sherdog URL into *Sherdog URLs*. Every bout comes back as its own row, with both fighters, the winner, method, round and time.

**Which promotions does it cover?** UFC, PFL, Bellator, ONE and Rizin by name, and any other promotion through its Sherdog organization URL.

**Can I get results as soon as an event ends?** Yes. Schedule the Actor with *Include upcoming events* and *Only return what changed* on. The announced card comes back once, and each bout comes back again when its result is filled in.

**Does it handle draws and no contests?** Yes. `isDraw` and `isNoContest` come from the result itself, and `winner` stays empty rather than naming whoever is listed first.

***

### Pricing

Pay per event: you are charged for each **record returned** - one bout, one event, or one fighter with their whole fight history. Rows that explain a problem - an unreadable page, a wrong or ambiguous fighter, a filter that matched nothing, a result cut by your maximum, a monitoring run with nothing new - are never charged.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

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

fights = one row per bout on an event card, with both fighters, the winner, method, round and time (the default). events = one row per event. fighters = one row per fighter, with the pro record, height, weight, gym, nationality and the full fight history.

## `organizations` (type: `array`):

UFC, PFL, Bellator, ONE or Rizin by name, or any promotion's Sherdog URL (for example https://www.sherdog.com/organizations/Professional-Fighters-League-12241). Its newest events are read. When nothing at all is given, the newest UFC events are read.

## `maxEvents` (type: `integer`):

Events are read newest first. A big card holds roughly 10-15 bouts. In Fighters mode, every fighter on these cards is read.

## `startUrls` (type: `array`):

Optional. Fighter, event or organization pages from sherdog.com, for example https://www.sherdog.com/fighter/Jon-Jones-27944 or https://www.sherdog.com/events/UFC-309-Jones-vs-Miocic-103896. Event URLs give the full card; fighter URLs give the record (set What to collect to Fighters).

## `fighterNames` (type: `array`):

In Fighters mode: fighters to look up by name on Sherdog (exact name, accents and capital letters ignored). In the other modes: keep only bouts that involve one of these fighters (partial match).

## `includeUpcoming` (type: `boolean`):

Off: only events that have happened are read from an organization. On: the announced upcoming cards come first, with empty result columns that fill in once the event is over.

## `maxRecords` (type: `integer`):

The most rows this run may return and charge for. When the limit cuts the result, rows are taken evenly from every event, so no event disappears completely, and a free row tells you what was left out.

## `weightClasses` (type: `array`):

Keep only records in these weight classes (for example Lightweight, Women's Strawweight). Matching is case-insensitive and partial.

## `keywords` (type: `array`):

Keep only records whose event name, bout, fighter names, location, method, gym or nationality contain these words.

## `keywordMatch` (type: `string`):

any = at least one keyword must appear. all = every keyword must appear.

## `excludeKeywords` (type: `array`):

Drop records containing any of these words. Applied to the same fields as Keywords above.

## `monitoringMode` (type: `boolean`):

Fighters mode: only fighters with a new fight on their record. Fights mode: new bouts, and bouts whose result has been filled in. Events mode: new events, and events that have now taken place. Nothing is charged twice for the same state.

## `resetMonitoringState` (type: `boolean`):

Clears that memory once, so this run returns everything again.

## `maxRequests` (type: `integer`):

A hard ceiling on how many pages this run may fetch from sherdog.com. Pages are read one at a time with a pause, so the site sees no more than a person browsing.

## `useProxy` (type: `boolean`):

Off by default: sherdog.com answers a plain connection. Turn this on only if you see pages failing to load.

## Actor input object example

```json
{
  "mode": "fights",
  "organizations": [
    "UFC"
  ],
  "maxEvents": 1,
  "includeUpcoming": false,
  "maxRecords": 100,
  "keywordMatch": "any",
  "monitoringMode": false,
  "resetMonitoringState": false,
  "maxRequests": 200,
  "useProxy": false
}
```

# Actor output Schema

## `results` (type: `string`):

In fights mode, one row per bout on the card: the event with its date, location and organization, both fighters with their Sherdog ids, each fighter's result, the winner, the method and its detail, the round and time it ended, the referee and the bout's place on the card. In events mode, one row per event with its date, location, organization and whether it has happened yet. In fighters mode, one row per fighter with the pro record (wins, losses, draws, no contests), wins and losses by method, height, weight, gym, nationality, date of birth, the next booked fight and every pro and amateur fight with opponent, result, method, round, time, date and event. Pages that could not be read, addresses that led to a different fighter, names that matched nobody or several people, filters that matched nothing and rows left out by your maximum each come back as their own row and are not charged.

# 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 = {
    "mode": "fights",
    "organizations": [
        "UFC"
    ],
    "maxEvents": 1,
    "maxRecords": 100,
    "maxRequests": 200
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/sherdog-fight-history").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 = {
    "mode": "fights",
    "organizations": ["UFC"],
    "maxEvents": 1,
    "maxRecords": 100,
    "maxRequests": 200,
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/sherdog-fight-history").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 '{
  "mode": "fights",
  "organizations": [
    "UFC"
  ],
  "maxEvents": 1,
  "maxRecords": 100,
  "maxRequests": 200
}' |
apify call neverempty/sherdog-fight-history --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/sherdog-fight-history"
        }
    }
}
```

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/eYt9mddpjIydqoglG/builds/IjBu46wrWUd0c7Z8p/openapi.json
