client

Implementation of Steam client based on gevent

Note

Additional features are located in separate submodules. All functionality from builtins is inherited by default.

Note

Optional features are available as mixins. This allows the client to remain light yet flexible.

class steam.client.SteamClient

Bases: steam.core.cm.CMClient, steam.client.builtins.BuiltinBase

EVENT_AUTH_CODE_REQUIRED = 'auth_code_required'

When either email or 2FA code is needed for login

EVENT_CHANNEL_SECURED = 'channel_secured'
EVENT_CHAT_MESSAGE = 'chat_message'
EVENT_CONNECTED = 'connected'
EVENT_DISCONNECTED = 'disconnected'
EVENT_EMSG = 0
EVENT_ERROR = 'error'
EVENT_LOGGED_ON = 'logged_on'

After successful login

EVENT_NEW_LOGIN_KEY = 'new_login_key'

After a new login key is accepted

EVENT_RECONNECT = 'reconnect'
PROTOCOL_TCP = 0
PROTOCOL_UDP = 1
anonymous_login()

Login as anonymous user

Returns:logon result, see CMsgClientLogonResponse.eresult
Return type:EResult
auto_discovery = True
cell_id = 0
change_status(**kwargs)

Set name, persona state, flags

Note

Changing persona state will also change persona_state

Parameters:
  • persona_state (EPersonaState) – persona state (Online/Offline/Away/etc)
  • player_name (str) – profile name
  • persona_state_flags (EPersonaStateFlag) – persona state flags
channel_hmac = None
channel_key = None
channel_secured = False
chat_mode = 2

chat mode (0=old chat, 2=new chat)

cli_login(username='', password='')

Generates CLI prompts to complete the login process

Parameters:
  • username (str) – optionally provide username
  • password (str) – optionally provide password
Returns:

logon result, see CMsgClientLogonResponse.eresult

Return type:

EResult

Example console output after calling cli_login()

In [5]: client.cli_login()
Steam username: myusername
Password:
Steam is down. Keep retrying? [y/n]: y
Invalid password for 'myusername'. Enter password:
Enter email code: 123
Incorrect code. Enter email code: K6VKF
Out[5]: <EResult.OK: 1>
cm_servers = None
connect(*args, **kwargs)

Attempt to establish connection, see CMClient.connect()

connected = False
count_listeners(event)

Returns a count of how many listeners are registered registed for a specific event

Parameters:event – event identifier
Returns:number of listeners
Return type:int
credential_location = None

location for sentry

current_games_played = []
current_jobid = 0
current_server_addr = None
disconnect(*args, **kwargs)

Close connection, see CMClient.disconnect()

emit(event, *args)

Emit event with some arguments

Parameters:
  • event (any type) – event identifier
  • args – any or no arguments
games_played(app_ids)

Set the apps being played by the user

Parameters:app_ids (list) – a list of application ids

These app ids will be recorded in current_games_played.

get_access_tokens(app_ids=[], package_ids=[])

Get access tokens

Parameters:
  • app_ids (list) – list of app ids
  • package_ids (list) – list of package ids
Returns:

dict with apps and packages containing their access tokens, see example below

Return type:

dict, None

{'apps':     {123: 8888888886, ...},
 'packages': {456: 6666666666, ...}
}
get_app_ticket(app_id)

Get app ownership ticket

Parameters:app_id (int) – app id
Returns:CMsgClientGetAppOwnershipTicketResponse
Return type:proto message
get_cdn_auth_token(depot_id, hostname)

Get CDN authentication token

Note

This token is no longer needed for access to CDN files

Parameters:
  • depot_id (int) – depot id
  • hostname (str) – cdn hostname
Returns:

CMsgClientGetCDNAuthTokenResponse

Return type:

proto message

get_changes_since(change_number, app_changes=True, package_changes=False)

Get changes since a change number

Parameters:
  • change_number (int) – change number to use as stating point
  • app_changes (bool) – whether to inclued app changes
  • package_changes (bool) – whether to inclued package changes
Returns:

CMsgClientPICSChangesSinceResponse

Return type:

proto message instance, or None on timeout

get_depot_key(app_id, depot_id)

Get depot decryption key

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

CMsgClientGetDepotDecryptionKeyResponse

Return type:

proto message

get_encrypted_app_ticket(app_id, userdata)

Gets the encrypted app ticket :param app_id: app id :type app_id: int :param userdata: userdata :type userdata: bytes :return: EncryptedAppTicket <https://github.com/ValvePython/steam/blob/39627fe883feeed2206016bacd92cf0e4580ead6/protobufs/encrypted_app_ticket.proto>_ :rtype: proto message

get_leaderboard(app_id, name)

New in version 0.8.2.

Find a leaderboard

Parameters:
  • app_id (int) – application id
  • name (str) – leaderboard name
Returns:

leaderboard instance

Return type:

SteamLeaderboard

Raises:

LookupError on message timeout or error

get_player_count(app_id, timeout=5)

Get numbers of players for app id

Parameters:app_id (int) – app id
Returns:number of players
Return type:int, EResult
get_product_info(apps=[], packages=[], auto_access_tokens=True, timeout=15)

Get product info for apps and packages

Parameters:
  • apps (list) – items in the list should be either just app_id, or dict
  • packages (list) – items in the list should be either just package_id, or dict
  • auto_access_token (bool) – automatically request and fill access tokens
Returns:

dict with apps and packages containing their info, see example below

Return type:

dict, None

{'apps':     {570: {...}, ...},
 'packages': {123: {...}, ...}
}

Access token is needed to access full information for certain apps, and also package info. Each app and package has its’ own access token. If a token is required then _missing_token=True in the response.

App access tokens are obtained by calling get_access_tokens(), and are returned only when the account has a license for the specified app. Example code:

result = client.get_product_info(apps=[123])

if result['apps'][123]['_missing_token']:
    tokens = client.get_access_token(apps=[123])

    result = client.get_product_info(apps=[{'appid': 123,
                                            'access_token': tokens['apps'][123]
                                            }])

Note

It is best to just request access token for all apps, before sending a product info request.

Package tokens are located in the account license list. See licenses

result = client.get_product_info(packages=[{'packageid': 123,
                                            'access_token': client.licenses[123].access_token,
                                            }])
get_sentry(username)

Returns contents of sentry file for the given username

Note

returns None if credential_location is not set, or file is not found/inaccessible

Parameters:username (str) – username
Returns:sentry file contents, or None
Return type:bytes, None
get_user(steam_id, fetch_persona_state=True)

Get SteamUser instance for steam id

Parameters:
  • steam_id (int, SteamID) – steam id
  • fetch_persona_state (bool) – whether to request person state when necessary
Returns:

SteamUser instance

Return type:

SteamUser

get_web_session(language='english')

Get a requests.Session that is ready for use

See get_web_session_cookies()

Note

Auth cookies will only be send to (help|store).steampowered.com and steamcommunity.com domains

Note

The session is valid only while SteamClient instance is logged on.

Parameters:language (str) – localization language for steam pages
Returns:authenticated Session ready for use
Return type:requests.Session, None
get_web_session_cookies()

Get web authentication cookies via WebAPI’s AuthenticateUser

Note

The cookies are valid only while SteamClient instance is logged on.

Returns:dict with authentication cookies
Return type:dict, None
idle()

Yeild in the current greenlet and let other greenlets run

licenses = None
logged_on = None

indicates logged on status. Listen to logged_on when change to True

login(username, password='', login_key=None, auth_code=None, two_factor_code=None, login_id=None)

Login as a specific user

Parameters:
  • username (str) – username
  • password (str) – password
  • login_key (str) – login key, instead of password
  • auth_code (str) – email authentication code
  • two_factor_code (str) – 2FA authentication code
  • login_id (int) – number used for identifying logon session
Returns:

logon result, see CMsgClientLogonResponse.eresult

Return type:

EResult

Note

Failure to login will result in the server dropping the connection, error event is fired

auth_code_required event is fired when 2FA or Email code is needed. Here is example code of how to handle the situation.

@steamclient.on(steamclient.EVENT_AUTH_CODE_REQUIRED)
def auth_code_prompt(is_2fa, code_mismatch):
    if is_2fa:
        code = input("Enter 2FA Code: ")
        steamclient.login(username, password, two_factor_code=code)
    else:
        code = input("Enter Email Code: ")
        steamclient.login(username, password, auth_code=code)

Codes are required every time a user logins if sentry is not setup. See set_credential_location()

login_key = None

can be used for subsequent logins (no 2FA code will be required)

logout()

Logout from steam. Doesn’t nothing if not logged on.

Note

The server will drop the connection immediatelly upon logout.

on(event, callback=None, once=False)

Registers a callback for the specified event

Parameters:
  • event – event name
  • callback – callback function

Can be as function decorator if only event param is specified.

@instaceOfSomeClass.on("some event")
def handle_event():
    pass

instaceOfSomeClass.on("some event", handle_event)

To listen for any event, use None as event identifier.

once(event, callback=None)

Register a callback, but call it exactly one time

See eventemitter.EventEmitter.on()

persona_state = 1
reconnect(maxdelay=30, retry=0)

Implements explonential backoff delay before attempting to connect. It is otherwise identical to calling CMClient.connect(). The delay is reset upon a successful login.

Parameters:
Returns:

successful connection

Return type:

bool

register_product_key(key)

Register/Redeem a CD-Key

Parameters:key (str) – CD-Key
Returns:format (eresult, result_details, receipt_info)
Return type:tuple

Example receipt_info:

{'BasePrice': 0,
  'CurrencyCode': 0,
  'ErrorHeadline': '',
  'ErrorLinkText': '',
  'ErrorLinkURL': '',
  'ErrorString': '',
  'LineItemCount': 1,
  'PaymentMethod': 1,
  'PurchaseStatus': 1,
  'ResultDetail': 0,
  'Shipping': 0,
  'Tax': 0,
  'TotalDiscount': 0,
  'TransactionID': UINT_64(111111111111111111),
  'TransactionTime': 1473000000,
  'lineitems': {'0': {'ItemDescription': 'Half-Life 3',
    'TransactionID': UINT_64(11111111111111111),
    'packageid': 1234}},
  'packageid': -1}
relogin()

Login without needing credentials, essentially remember password. The login_key is acquired after successful login and it will be automatically acknowledged. Listen for the new_login_key event. After that the client can relogin using this method.

Note

Only works when relogin_available is True.

if client.relogin_available: client.relogin()
else:
    client.login(user, pass)
Returns:login result
Return type:EResult
relogin_available

True when the client has the nessesary data for relogin()

remove_all_listeners(event=None)

Removes all registered callbacks, or all registered callbacks for a specific event

Parameters:event – event identifier
remove_listener(event, callback)

Removes callback for the specified event

Parameters:
request_free_license(app_ids)

Request license for free app(s)

Parameters:app_ids (list) – list of app ids
Returns:format (EResult, result_details, receipt_info)
Return type:tuple
request_persona_state(steam_ids, state_flags=863)

Request persona state data

Parameters:
run_forever()

Transfer control the gevent event loop

This is useful when the application is setup and ment to run for a long time

send(message, body_params=None)

Send a message to CM

Parameters:
  • message (Msg, MsgProto) – a message instance
  • body_params (dict) – a dict with params to the body (only MsgProto)
send_job(message, body_params=None)

Send a message as a job

Note

Not all messages are jobs, you’ll have to find out which are which

Parameters:
  • message (Msg, MsgProto) – a message instance
  • body_params (dict) – a dict with params to the body (only MsgProto)
Returns:

jobid event identifier

Return type:

str

To catch the response just listen for the jobid event.

jobid = steamclient.send_job(my_message)

resp = steamclient.wait_event(jobid, timeout=15)
if resp:
    (message,) = resp
send_job_and_wait(message, body_params=None, timeout=None, raises=False)

Send a message as a job and wait for the response.

Note

Not all messages are jobs, you’ll have to find out which are which

Parameters:
  • message (Msg, MsgProto) – a message instance
  • body_params (dict) – a dict with params to the body (only MsgProto)
  • timeout (int) – (optional) seconds to wait
  • raises (bool) – (optional) On timeout if False return None, else raise gevent.Timeout
Returns:

response proto message

Return type:

Msg, MsgProto

Raises:

gevent.Timeout

send_message_and_wait(message, response_emsg, body_params=None, timeout=None, raises=False)

Send a message to CM and wait for a defined answer.

Parameters:
  • message (Msg, MsgProto) – a message instance
  • response_emsg (EMsg,:class:int) – emsg to wait for
  • body_params (dict) – a dict with params to the body (only MsgProto)
  • timeout (int) – (optional) seconds to wait
  • raises (bool) – (optional) On timeout if False return None, else raise gevent.Timeout
Returns:

response proto message

Return type:

Msg, MsgProto

Raises:

gevent.Timeout

send_um(method_name, params=None)

Send service method request

Parameters:
  • method_name (str) – method name (e.g. Player.GetGameBadgeLevels#1)
  • params (dict) – message parameters
Returns:

job_id identifier

Return type:

str

Listen for jobid on this object to catch the response.

send_um_and_wait(method_name, params=None, timeout=10, raises=False)

Send service method request and wait for response

Parameters:
  • method_name (str) – method name (e.g. Player.GetGameBadgeLevels#1)
  • params (dict) – message parameters
  • timeout (int) – (optional) seconds to wait
  • raises (bool) – (optional) On timeout if False return None, else raise gevent.Timeout
Returns:

response message

Return type:

proto message instance

Raises:

gevent.Timeout

session_id = None
set_credential_location(path)

Sets folder location for sentry files

Needs to be set explicitly for sentries to be created.

set_ui_mode(uimode)

Set UI mode. Show little icon next to name in friend list. (e.g phone, controller, other)

Parameters:uimode (EClientUIMode) – UI mode integer

These app ids will be recorded in current_games_played.

sleep(seconds)

Yeild and sleep N seconds. Allows other greenlets to run

steam_id = SteamID(id=0, type='Invalid', universe='Invalid', instance=0)
store_sentry(username, sentry_bytes)

Store sentry bytes under a username

Parameters:username (str) – username
Returns:Whenver the operation succeed
Return type:bool
user = None
username = None

username when logged on

verbose_debug = False
wait_event(event, timeout=None, raises=False)

Blocks until an event and returns the results

Parameters:
  • event – event identifier
  • timeout (int) – (optional)(default:None) seconds to wait
  • raises (bool) – (optional)(default:False) On timeout if False return None, else raise gevent.Timeout
Returns:

returns event arguments in tuple

Return type:

None, or tuple

Raises:

gevent.Timeout

Handling timeout

args = ee.wait_event('my event', timeout=5)
if args is None:
    print "Timeout!"
wait_msg(event, timeout=None, raises=None)

Wait for a message, similiar to wait_event()

Parameters:
  • event (EMsg or str) – event id
  • timeout (int) – seconds to wait before timeout
  • raises (bool) – On timeout when False returns None, else raise gevent.Timeout
Returns:

returns a message or None

Return type:

None, or proto message

Raises:

gevent.Timeout

steam.client.random() → x in the interval [0, 1).