{
  "openapi": "3.0.1",
  "info": {
    "title": "SofaScore Tennis Scraper — Live Scores, Stats & Point-by-Point",
    "description": "Scrape every ATP, WTA, Challenger and ITF tennis match on SofaScore by date, tournament or player — set-by-set scores, 42 match statistics, point-by-point rally data, serve and return splits, H2H record, seeds, prize money, court and surface. No API key.",
    "version": "0.1",
    "x-build-id": "k6Q6kAqsYRxfTK29D"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapersdelight~sofascore-tennis-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapersdelight-sofascore-tennis-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/scrapersdelight~sofascore-tennis-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapersdelight-sofascore-tennis-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/scrapersdelight~sofascore-tennis-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapersdelight-sofascore-tennis-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "title": "What to scrape",
            "enum": [
              "date",
              "live",
              "tournament",
              "player"
            ],
            "type": "string",
            "description": "How to find the matches.\n\n- **date** — every ATP, WTA, Challenger and ITF match played on the given day(s). This is the full world card.\n- **live** — only the matches in progress right now.\n- **tournament** — only the tournaments you list below (fill in *Unique tournament IDs*).\n- **player** — one or more players' matches (fill in *Player names* or *Player IDs*).\n\nLeave it on `date` and the actor still switches automatically if you fill in tournament IDs or player names.",
            "default": "date"
          },
          "dates": {
            "title": "Dates (YYYY-MM-DD)",
            "type": "array",
            "description": "Which day(s) to scrape, in UTC, e.g. `2026-09-03`. Leave empty for today. SofaScore serves both past results and future fixtures, so a date in either direction works.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "daysBack": {
            "title": "Also include N previous days",
            "minimum": 0,
            "maximum": 30,
            "type": "integer",
            "description": "Adds the N days before each date above. `0` = just that day, `6` = a full week of results. Useful for backfilling a season without listing every date by hand.",
            "default": 0
          },
          "uniqueTournamentIds": {
            "title": "Unique tournament IDs",
            "type": "array",
            "description": "SofaScore *unique tournament* IDs — the number at the end of a tournament URL, e.g. `2449` in `sofascore.com/tennis/tournament/atp/us-open/2449`. Every row this actor returns carries its own `uniqueTournamentId`, so a first run by date tells you the IDs you want.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "wholeSeason": {
            "title": "Whole current season (tournament mode)",
            "type": "boolean",
            "description": "In tournament mode, ignore the dates and walk the tournament's current season from its most recent match backwards. Use *Max pages per tournament* to control how far back.",
            "default": false
          },
          "maxPagesPerTournament": {
            "title": "Max pages per tournament (whole season)",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Pages of season history to walk per tournament — 30 matches per page, contiguous with no overlap.",
            "default": 3
          },
          "playerNames": {
            "title": "Player names",
            "type": "array",
            "description": "Player names to look up on SofaScore, e.g. `Carlos Alcaraz`. Each name is resolved to the tennis player it matches and their matches are returned, newest first.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "playerIds": {
            "title": "Player IDs",
            "type": "array",
            "description": "SofaScore player IDs, if you already have them — the number at the end of a player URL, e.g. `112783` in `sofascore.com/tennis/player/berrettini-matteo/112783`. Every row carries `homeId` / `awayId`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxMatchesPerPlayer": {
            "title": "Max matches per player",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "How far back to walk each player's match history.",
            "default": 30
          },
          "matchStatus": {
            "title": "Match status",
            "enum": [
              "any",
              "finished",
              "inprogress",
              "notstarted"
            ],
            "type": "string",
            "description": "Keep only matches in this state. `finished` gives completed results (the ones that carry statistics and point-by-point), `inprogress` gives live matches, `notstarted` gives fixtures.",
            "default": "any"
          },
          "tours": {
            "title": "Tours / tournament filter",
            "type": "array",
            "description": "Case-insensitive text filter on the tour and tournament name, e.g. `ATP`, `WTA`, `Challenger`, `ITF`, `US Open`. Leave empty for every tour. A match is kept if it matches any entry.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "enrichMatches": {
            "title": "Enrich each match (statistics, point-by-point, momentum, H2H, venue, player bios)",
            "type": "boolean",
            "description": "Fetch the deep per-match data. Off, you get the fast match row: tournament, players, rankings, set-by-set score, live game point, winner. On, each match also gets the full statistics sheet, the point-by-point rally log, the momentum curve, the head-to-head record, the court and both players' bios — via 4-7 extra requests, billed as *Per match enriched*.",
            "default": true
          },
          "includeStatistics": {
            "title": "· include the match statistics sheet",
            "type": "boolean",
            "description": "42 statistics per player — aces, double faults, 1st/2nd serve in and won, break points saved and converted, winners and errors by stroke, unforced errors, return points, tiebreaks — for the whole match AND for each individual set. Only applies when enrichment is on.",
            "default": true
          },
          "includePointByPoint": {
            "title": "· include point-by-point",
            "type": "boolean",
            "description": "Every point of every game of every set, with the running game score, who was serving and who won the game. This is the field most tennis feeds do not carry. Only applies when enrichment is on.",
            "default": true
          },
          "includeMomentum": {
            "title": "· include the momentum curve",
            "type": "boolean",
            "description": "SofaScore's per-game 'tennis power' value with a flag for the games where a break happened. Only applies when enrichment is on.",
            "default": true
          },
          "includeH2H": {
            "title": "· include the head-to-head record",
            "type": "boolean",
            "description": "The two players' career win-loss record against each other. Only applies when enrichment is on.",
            "default": true
          },
          "includeVotes": {
            "title": "· include crowd predictions",
            "type": "boolean",
            "description": "How SofaScore's users voted on the match before it started. Only applies when enrichment is on.",
            "default": true
          },
          "includeOdds": {
            "title": "· include bookmaker odds",
            "type": "boolean",
            "description": "Adds SofaScore's bookmaker markets (full time, set winner, totals) as an `odds` array. OFF by default — redistributing betting odds is a licensing question for your jurisdiction, so it is an explicit opt-in. Only applies when enrichment is on.",
            "default": false
          },
          "maxMatches": {
            "title": "Max matches",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after this many matches. A full world day is 1,000+ matches, so the default is deliberately modest — raise it once you know the scope you want. `0` = no limit. Tournaments are visited biggest-first (SofaScore's own priority order), so a capped run returns the matches people actually watch.",
            "default": 40
          },
          "maxConcurrency": {
            "title": "Concurrent requests",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "How many SofaScore requests to run at once. 8 is a good balance; lower it if you see many retries.",
            "default": 8
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "**Required — do not switch this off.** SofaScore answers 403 to Apify's own datacenter IPs on 100% of calls (measured 8/8). Apify Proxy with the RESIDENTIAL group is the only lane that works (measured 4/4) and is preselected here. Your own residential proxy URLs work too.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}