Async library for interfacing with the replay REST API of Dragonball FighterZ.
Massively inspired by Felix WindstrΓΆm's creation of http://ratingupdate.info/.
Please keep in mind this is a Python implementation of dealing with the API. Depending on how Messagepack is done on your preferred language, some aspects may change.
How the API works
The API works by sending a POST request to https://dbf.channel.or.jp/api/catalog/get_replay.
The header needs to contain Content Type: application/x-www-form-urlencoded as you need to pass a hex (non-escaped) encoded messagepack to the server.
The server will then give a response back in hex encoded messagepack which can be unpacked.
The request for the replay requires having a very specific timestamp(?) which is in hex, this can be gotten by using sending a POST request to https://dbf.channel.or.jp/api/user/login. Follows the same suite as above.
headers = {
"Host": "dbf.channel.or.jp",
'Content-Type': 'application/x-www-form-urlencoded',
}These are the only headers needed for sending a request to the API endpoints (For a lot of these headers, they're VERY specific to your own game login which can be found by using a packet sniffer application such as Fiddler to find these out)
[
[
"",
"",
2,
"0.0.3",
103
],
[
"76561198077238919", # SteamID in decimal
"110000106f8de9a", # SteamID in hexadecimal
256,
0
]
]The workflow for sending to api is:
- Get json and pack to msgpack
- Add to another json and add to the key "data", and transform the escaped hex to hex. For example:
binascii.hexlify(msgpack.packb(loginData)). Example of the hex would bedd00000002dd00000005a0a002a5302e302e3303dd00000004b13736353631313938303737323338393339af313130303030313036663864653962cd010000 - POST to the api as
data=and response will be plaintext msgpack to be decoded usingmsgpack.unpackb()
After, you get a response from the server such as the following:
[
[
"636d55d3a3736",
0,
"2022/11/11 04:49:39",
"0.0.3",
"0.0.3",
"0.0.3",
"",
""
],
[
0,
[
"180205073302944621",
"Deviance",
"76561198077238939",
"110000106f8de9b",
869826
]
]
]Which you take the first value (in the example above would be 636d55d3a3736) and put that into the JSON for the get_replay_url below as this is the handshake token needed to verify the user.
[
[
"180205073302944621", # player ID doing request, please use your own player ID as this rate limits the actual user from playing
"636d55d3a3736", # handshake token taken from loggging into the servers
2, # unknown
"0.0.3", # game version
103 # unknown, probably platform such as PC and PS4
],
[
7, # unknown
1, # order by [1: newest, 2: views, etc]
0, # number of replay pages scrolled (starts at 0), max is 50000 upwards but gets very slow so best to stick to 5000 or less
10, # number of matches queried, can be more than 10000
[
35, # current game build number
-1, # character list, [all character: -1, ssj goku: 0, ssj vegeta: 1, etc] always goes upwards (easy to make enum)
102, # query for play mode, [all modes: -1 , ranked: 102 , casual: 104, arena: 103, ring: 105, ring party match: 107, tournament: 110]
1, # queries from this number downwards up to 10 ranks (starts at 1), can go up to 50000 upwards but gets very slow so best to stick to 5000 or less
-1, # unknown
[]
]
]
]The workflow for sending to api is:
- Get json and pack to msgpack
- Add to another json and add to the key "data", and transform the escaped hex to hex. For example:
binascii.hexlify(msgpack.packb(replayData)) - POST to the api as
data=and response will be plaintext msgpack to be decoded usingmsgpack.unpackb()
OR
- Get msgpack data (such as
9295b2313830323035303733333032393434363233ad3633356661306433313734303802a5302e302e3303950701000a961cffff01ff90) - Add to another json and add to the key "data"
- POST to the api as
data=and response will be plaintext msgpack to be decoded usingmsgpack.unpackb()
You can unpack the messagepack using msgpack.unpackb(), however each item in the JSON will be encoded so manually decoding
via the functions provided (decode_list and subsequently decode_dict) helps it be parsed as a json
The JSON always has 10 matches inside it with the first player always being the winner. A shortened example with only one match is annotated below:
[
[
"6365b7aff20b5",
0,
"2022/11/05 10:09:03", # time it was queried in JST (irrelevant to the actual match stats)
"0.0.3",
"0.0.3",
"0.0.3",
"",
""
],
[
0,
10,
[
[
221105064149496874, # unique identifer for the match itself
28,
"WIN_PlmRVer035",
[ # characters for player who won
0,
39,
38
],
[# characters for player who lost
0,
31,
19
],
[ # person who won
[
"211127010233268016", # player ID who won
"Deviance",
"76561199013492555",
"11000013ec6f74b",
856119
],
[
"0",
"",
"",
"",
0
],
[
"0",
"",
"",
"",
0
]
],
[ # person who lost
[
"210319054513269637", # player ID who lost
"paddu",
"76561199080463934",
"110000142c4de3e",
829720
],
[
"0",
"",
"",
"",
0
],
[
"0",
"",
"",
"",
0
]
],
1,
"2022-11-05 20:41:43", # timestamp of the match (UTC? or Japan time?)
102,
0,
1,
"",
"",
""
]
]
]
]Reference guide: All reverse engineered parts of the API
[
[
"player_id": "180205073302944623",
"session_token": "6a425002dd0b1",
"auth_type: 2",
"client_version": "0.0.3",
"build_id: 103"
],
[
"opcode: 7",
"order_by: 1",
"replay_page_offset: 0",
"limit: 10",
[
"mode: 104", // all modes: -1 , ranked: 102 , casual: 104, arena: 103, ring: 105, ring party match: 107, tournament: 110
"character_filter: -1", // [all character: -1, ssj goku: 0, ssj vegeta: 1, etc] always goes upwards
"version_filter: 35",
"number_of_replays: 1",
"unknown1: -1",
"unknown_list: []"
]
]
][ [ AUTH_BLOCK ], [ QUERY_BLOCK ] ]
[ playerId, sessionToken, authType, clientVersion, buildId ]
- playerId β internal account ID
- sessionToken β login/session token
- authType β login type flag
- clientVersion β game version (e.g. "0.0.3")
- buildId β internal build number
[ mode, page, offset, limit, filters ]
- -1 = all modes
- 102 = ranked
- 103 = arena
- 104 = casual
- 105 = ring
- 107 = ring party
- 110 = tournament
- page β page index
- offset β usually 0
- number of replays to fetch
- example: 10 = latest 10 replays
[ character, unknown, version, rankedFlag, unknown, extraList ]
- -1 = all characters
- 0+ = character enum ID
[ [ SERVER_META ], [ RESULT_BLOCK ] ]
[ sessionId, statusCode, serverTime, clientVersion, serverVersion, latestVersion, message, updateUrl ]
- statusCode = 0 success
- serverTime = UTC timestamp string
- version fields = build/version info
[ statusCode, replayCount, replayList ]
[ replayId, characterSet, gameVersion, teamA, teamB, playerA, playerB, flags, timestamp, ratingBucket, resultFlags ]
[ char1, char2, char3 ]
- 0+ = character enum IDs
- -1 = none
[ playerId, displayName, steamId64, steamIdHex, profileId ]
- numeric build (e.g. 35)
- matches string version (e.g. WIN_PlmRVer035)
- UTC string format
- example: 2026-06-29 17:17:36
- -1 = wildcard / no filter
- integers = enums or flags
- arrays = structured objects
- protocol is RPC-style, not REST
- optimized for replay retrieval and matchmaking history