cdn

The CDNClient class provides a simple API for downloading Steam content from SteamPipe

Initializing CDNClient requires a logged in SteamClient instance

mysteam = SteamClient()
...
mycdn = CDNClient(mysteam)

Getting depot manifests for an app

>>> mycdn.get_manifests(570)
[<CDNDepotManifest('Dota 2 Content', app_id=570, depot_id=373301, gid=6397590570861788404, creation_time='2019-06-29 16:03:11')>,
 <CDNDepotManifest('Dota 2 Content 2', app_id=570, depot_id=381451, gid=5769691971272474272, creation_time='2019-06-29 00:19:02')>,
 <CDNDepotManifest('Dota 2 Content 3', app_id=570, depot_id=381452, gid=3194393866044592918, creation_time='2019-06-27 00:05:38')>,
 <CDNDepotManifest('Dota 2 Content 4', app_id=570, depot_id=381453, gid=8005824150061180163, creation_time='2019-06-08 07:49:57')>,
 <CDNDepotManifest('Dota 2 Content 5', app_id=570, depot_id=381454, gid=9003299908441378336, creation_time='2019-06-26 18:56:19')>,
 <CDNDepotManifest('Dota 2 Content 6', app_id=570, depot_id=381455, gid=8000458746487720619, creation_time='2019-06-29 00:19:43')>,
 <CDNDepotManifest('Dota 2 Win32', app_id=570, depot_id=373302, gid=3561463682334619841, creation_time='2019-06-29 00:16:28')>,
 <CDNDepotManifest('Dota 2 Win64', app_id=570, depot_id=373303, gid=6464064782313084040, creation_time='2019-06-29 00:16:43')>,
 <CDNDepotManifest('Dota 2 Mac', app_id=570, depot_id=373304, gid=5979018571482579541, creation_time='2019-06-29 00:16:59')>,
 <CDNDepotManifest('Dota 2 English', app_id=570, depot_id=373305, gid=4435851250675935801, creation_time='2015-06-01 20:15:37')>,
 <CDNDepotManifest('Dota 2 Linux', app_id=570, depot_id=373306, gid=4859464855297921815, creation_time='2019-06-29 00:17:25')>,
 <CDNDepotManifest('Dota 2 Korean', app_id=570, depot_id=373308, gid=8598853793233320583, creation_time='2019-03-05 17:16:49')>,
 <CDNDepotManifest('Dota 2 Simplified Chinese', app_id=570, depot_id=373309, gid=6975893321745168138, creation_time='2019-06-25 21:40:37')>,
 <CDNDepotManifest('Dota 2 Russian', app_id=570, depot_id=381456, gid=5425063725991897591, creation_time='2019-03-05 17:19:53')>,
 <CDNDepotManifest('Dota 2 Workshop tools', app_id=570, depot_id=381450, gid=8629205096668418087, creation_time='2019-06-29 16:04:18')>,
 <CDNDepotManifest('Dota 2 OpenGL Windows', app_id=570, depot_id=401531, gid=6502316736107281444, creation_time='2019-06-07 19:04:08')>,
 <CDNDepotManifest('Dota 2 Vulkan Common', app_id=570, depot_id=401535, gid=6405492872419215600, creation_time='2019-06-07 19:04:11')>,
 <CDNDepotManifest('Dota 2 Vulkan Win64', app_id=570, depot_id=401536, gid=3821288251412129608, creation_time='2019-06-25 21:42:29')>,
 <CDNDepotManifest('Dota 2 Vulkan Linux64', app_id=570, depot_id=401537, gid=3144805829218032316, creation_time='2019-06-17 16:54:43')>,
 <CDNDepotManifest('Dota 2 VR', app_id=570, depot_id=313255, gid=706332602567268673, creation_time='2017-10-04 18:52:14')>,
 <CDNDepotManifest('Dota 2 Vulkan Mac', app_id=570, depot_id=401538, gid=2223235822414824351, creation_time='2019-06-11 19:37:19')>]

>>> mycdn.get_manifests(570, filter_func=lambda depot_id, info: 'Dota 2 Content' in info['name'])
[<CDNDepotManifest('Dota 2 Content', app_id=570, depot_id=373301, gid=6397590570861788404, creation_time='2019-06-29 16:03:11')>,
 <CDNDepotManifest('Dota 2 Content 2', app_id=570, depot_id=381451, gid=5769691971272474272, creation_time='2019-06-29 00:19:02')>,
 <CDNDepotManifest('Dota 2 Content 3', app_id=570, depot_id=381452, gid=3194393866044592918, creation_time='2019-06-27 00:05:38')>,
 <CDNDepotManifest('Dota 2 Content 4', app_id=570, depot_id=381453, gid=8005824150061180163, creation_time='2019-06-08 07:49:57')>,
 <CDNDepotManifest('Dota 2 Content 5', app_id=570, depot_id=381454, gid=9003299908441378336, creation_time='2019-06-26 18:56:19')>,
 <CDNDepotManifest('Dota 2 Content 6', app_id=570, depot_id=381455, gid=8000458746487720619, creation_time='2019-06-29 00:19:43')>]

Listing files

>>> file_list = mycdn.iter_files(570)
>>> list(file_list)[:10]
[<CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota_addons\dungeon\particles\test_particle\generic_attack_crit_blur_rope.vpcf_c', 2134)>,
 <CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota_addons\dungeon\materials\blends\mud_brick_normal_psd_5cc4fe8b.vtex_c', 351444)>,
 <CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota_addons\hero_demo\scripts\vscripts\la_spawn_enemy_at_target.lua', 1230)>,
 <CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota_addons\winter_2018\particles\dark_moon\darkmoon_last_hit_effect_damage_flash_b.vpcf_c', 1386)>,
 <CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota_addons\dungeon\scripts\vscripts\abilities\siltbreaker_line_wave.lua', 3305)>,
 <CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota_addons\dungeon\materials\models\heroes\broodmother\broodmother_body_poison.vmat_c', 10888)>,
 <CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota\resource\cursor\workshop\sltv_shaker_cursor_pack\cursor_spell_default.ani', 4362)>,
 <CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota_addons\overthrow\panorama\images\custom_game\team_icons\team_icon_tiger_01_png.vtex_c', 18340)>,
 <CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota\resource\cursor\valve\ti7\cursor_attack_illegal.bmp', 4152)>,
 <CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota_addons\winter_2018\models\creeps\ice_biome\undeadtusk\undead_tuskskeleton01.vmdl_c', 13516)>

Reading a file directly from SteamPipe

>>> file_list = mycdn.iter_files(570, r'game\dota\gameinfo.gi')
>>> myfile = next(file_list)
<CDNDepotFile(570, 373301, 6397590570861788404, 'game\dota\gameinfo.gi', 6808)>
>>> print(myfile.read(80).decode('utf-8'))
"GameInfo"
{
        game            "Dota 2"
        title           "Dota 2"

        gamelogo 1
        type            multiplayer_only
...
class steam.client.cdn.CDNClient(client)

Bases: object

CDNClient allows loading and reading of manifests for Steam apps are used to list and download content

Parameters:client (SteamClient) – logged in SteamClient instance
DepotManifestClass

alias of CDNDepotManifest

app_depots = None

app depot info

beta_passwords = None

beta branch decryption keys

cdn_cmd(command, args)

Run CDN command request

Parameters:
  • command (str) – command name
  • args (str) – args
Returns:

requests response

Return type:

requests.Response

Raises:

SteamError – on error

cell_id = 0

Cell ID to use, initialized from SteamClient instance

check_beta_password(app_id, password)

Check branch beta password to unlock encrypted branches

Parameters:
  • app_id (int) – App ID
  • password (str) – beta password
Returns:

result

Return type:

EResult

depot_keys = None

depot decryption keys

fetch_content_servers(num_servers=20)

Update CS server list

Parameters:num_servers (int) – numbers of CS server to fetch
get_app_depot_info(app_id)
get_chunk(app_id, depot_id, chunk_id)

Download a single content chunk

Parameters:
  • app_id (int) – App ID
  • depot_id (int) – Depot ID
  • chunk_id (int) – Chunk ID
Returns:

chunk data

Return type:

bytes

Raises:

SteamError – error message

get_content_server(rotate=False)

Get a CS server for content download

Parameters:rotate (bool) – forcefully rotate server list and get a new server
get_depot_key(app_id, depot_id)

Get depot key, which is needed to decrypt files

Parameters:
  • app_id (int) – app id
  • depot_id (int) – depot id
Returns:

returns decryption key

Return type:

bytes

Raises:

SteamError – error message

get_manifest(app_id, depot_id, manifest_gid, decrypt=True)

Download a manifest file

Parameters:
  • app_id (int) – App ID
  • depot_id (int) – Depot ID
  • manifest_gid (int) – Manifest gid
  • decrypt (bool) – Decrypt manifest filenames
Returns:

manifest instance

Return type:

CDNDepotManifest

get_manifest_for_workshop_item(item_id)

Get the manifest file for a worshop item that is hosted on SteamPipe

Parameters:item_id (int) – Workshop ID
Returns:manifest instance
Return type:CDNDepotManifest
Raises:SteamError – error message
get_manifests(app_id, branch='public', password=None, filter_func=None, decrypt=True)

Get a list of CDNDepotManifest for app

Parameters:
  • app_id (int) – App ID
  • branch (str) – branch name
  • password (str) – branch password for locked branches
  • filter_func – Function to filter depots. func(depot_id, depot_info)
Returns:

list of CDNDepotManifest

Return type:

list [CDNDepotManifest]

Raises:

SteamError – error message

gpool = None

task pool

iter_files(app_id, filename_filter=None, branch='public', password=None, filter_func=None)

Like get_manifests() but returns a iterator that goes through all the files in all the manifest.

Parameters:
  • app_id (int) – App ID
  • filename_filter – wildcard filter for file paths
  • branch (str) – branch name
  • password (str) – branch password for locked branches
  • filter_func – Function to filter depots. func(depot_id, depot_info)
Returns:

generator of of CDN files

Return type:

[CDNDepotFile]

licensed_app_ids = None

app_ids that the SteamClient instance has access to

licensed_depot_ids = None

depot_ids that the SteamClient instance has access to

load_licenses()

Read licenses from SteamClient instance, required for determining accessible content

manifests = None

CDNDepotManifest instances

servers = deque([])

CS Server list

steam = None

SteamClient instance

class steam.client.cdn.CDNDepotFile(manifest, file_mapping)

Bases: steam.core.manifest.DepotFile

File-like object proxy for content files located on SteamPipe

Parameters:
  • manifest (CDNDepotManifest) – parrent manifest instance
  • file_mapping (ContentManifestPayload.FileMapping) – file mapping instance from manifest
chunks

File chunks instances

Type:list [ContentManifestPayload.FileMapping.ChunkData]
filename

Filename matching the OS

Type:str
filename_raw

Filename with null terminator and whitespaces removed

Type:str
flags

File flags

Type:EDepotFileFlag
is_directory
Type:bool
is_file
Type:bool
Type:bool
next()
read(length=-1)

Read bytes from the file

Parameters:length (int) – number of bytes to read. Read the whole file if not set
Returns:file data
Return type:bytes
readline()

Read a single line

Returns:single file line
Return type:bytes
readlines()

Get file contents as list of lines

Returns:list of lines
Return type:list [bytes]
seek(offset, whence=0)

Seen file

Parameters:
seekable
Type:bool
size

File size in bytes

Type:int
tell()
Type:int
class steam.client.cdn.CDNDepotManifest(cdn_client, app_id, data)

Bases: steam.core.manifest.DepotManifest

Holds manifest metadata and file list.

Parameters:
  • cdn_client (CDNClient) – CDNClient instance
  • app_id (int) – App ID
  • data (bytes) – serialized manifest data
DepotFileClass

alias of CDNDepotFile

PROTOBUF_ENDOFMANIFEST_MAGIC = 851711403
PROTOBUF_METADATA_MAGIC = 524817086
PROTOBUF_PAYLOAD_MAGIC = 1911953360
PROTOBUF_SIGNATURE_MAGIC = 461486103
creation_time
Type:int
decrypt_filenames(depot_key)

Decrypt all filenames in the manifest

Parameters:depot_key (bytes) – depot key
Raises:RuntimeError
depot_id
Type:int
deserialize(data)

Deserialize a manifest (compressed or uncompressed)

Parameters:data (bytes) – manifest data
filenames_encrypted
Type:bool
gid
Type:int
iter_files(pattern=None)
Parameters:pattern (str) – unix shell wildcard pattern, see fnmatch()
name = None

set only by CDNClient.get_manifests()

serialize(compress=True)

Serialize manifest

Parameters:compress (bytes) – wether the output should be Zip compressed
size_compressed
Type:int
size_original
Type:int
class steam.client.cdn.ContentServer

Bases: object

cell_id = 0
host = None
https = False
load = None
port = None
type = None
vhost = None
weighted_load = None
steam.client.cdn.decrypt_manifest_gid_2(encrypted_gid, password)

Decrypt manifest gid v2 bytes

Parameters:
  • encrypted_gid (bytes) – encrypted gid v2 bytes
  • password (byt) – encryption password
Returns:

manifest gid

Return type:

int

steam.client.cdn.get_content_servers_from_cs(cell_id, host='cs.steamcontent.com', port=80, num_servers=20, session=None)

Get a list of CS servers from a single CS server

Parameters:
  • cell_id (bytes) – location cell id
  • host (str) – CS server host
  • port (int) – server port number
  • num_servers (int) – number of servers to return
  • session (requests.Session) – requests Session instance
Returns:

list of CS servers

Return type:

list [ContentServer]

steam.client.cdn.get_content_servers_from_webapi(cell_id, num_servers=20)

Get a list of CS servers from Steam WebAPI

Parameters:
  • cell_id (bytes) – location cell id
  • num_servers (int) – number of servers to return
Returns:

list of CS servers

Return type:

list [ContentServer]