How to write down a tennis match: four open formats compared
4 open ways to record the points of a tennis match, compared on granularity, timestamps, tiebreaks, the server and licence. Each cell comes from the format's own published spec or README.
Pick by what you need to keep. A point string is the smallest way to store who won each point. Shot-level charting adds every stroke, at the cost of a person charting the match. A news schema carries scores between publishers. A JSON score object is what a live feed sends.
| Format | Granularity | Timestamps | Tiebreaks | Match tiebreak | Server | Licence |
|---|---|---|---|---|---|---|
| Point-by-point stringstennis_pointbypoint README (archived copy) | Point. One row per match, one character per point. | None per point. Each match has a date. | A slash shows each change of server inside a tie-break. | Not specified | A server1 column names who served first. Each point code is relative to the server. | CC BY-NC-SA 4.0 |
| Match Charting Project shot notationMatch Charting Project README and data dictionary | Shot. One row per point, with every shot coded. | Not specified | A TB? column flags the points played in a tie-break. | A match setting says how the final set ends. S means only a 10-point tie-break is played, A a 10-point tie-break at six all. | Svr is 1 or 2. Player 1 is always the one who served first. | CC BY-NC-SA 4.0 |
| IPTC SportsML tennisSportsML 3.1 tennis schema (XSD) | Match, set and game, with an optional action for each point. | Yes. Each action can carry a date and time, and sets and games a duration in minutes. | A score-tiebreaker attribute on the set holds the tie-break score. | Not specified | server-idref points to the player or team that served the point. | CC BY 4.0 (the schema) |
| Live Tennis API score objectLive Tennis API OpenAPI 3.1 document, Score schema | One state per accepted score change: sets, games in each set and points in the current game. | Yes. Each state has UTC timestamps and a sequence number that orders the states of a match. | is_tiebreak is true while a tie-break game is played. | The deciding set's slot holds the tie-break points while it is played, and is_tiebreak stays true for that set. | server is 1, 2 or null. | MIT for the specification. Data access is under the API terms. |
"Not specified" means the format's own document does not say.
What does each format look like?
Point-by-point strings
Each match is one string of point codes. S means the server won the point, R the returner, A an ace and D a double fault. A semicolon ends a game and a full stop ends a set. The repository that defined it is no longer online, so we read an archived copy.
SSAS;RSRRR;SDSSS
Source: tennis_pointbypoint README (archived copy), read on 8 November 2026.
Match Charting Project shot notation
Contributors code every shot of a point by hand. Serves are coded by direction (4 is wide, 5 the body and 6 down the T). Each shot gets a letter, such as f for forehand. The last shot says how the point ended, for example n for the net.
Source: Match Charting Project README and data dictionary, read on 8 November 2026.
IPTC SportsML tennis
An XML standard from IPTC, the news media standards body, for sending sports results between publishers. Its tennis schema adds set and game scores, and an action element for each point.
Source: SportsML 3.1 tennis schema (XSD), read on 8 November 2026.
Live Tennis API score object
The JSON object our REST API and WebSocket feed send for a match's score: sets, games in each set and points in the current game. The example is the games of a match whose deciding set is a match tie-break at 10-5.
"games": [[6, 4, 10], [4, 6, 5]]
Source: Live Tennis API OpenAPI 3.1 document, Score schema, read on 8 November 2026.
Where do the round and tier codes come from?
The formats above record points. For the codes around a match, such as the round and the tier, see our tennis data codes index. Each code links its rulebook.
Every spec was read on 8 November 2026.