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
change_email(password, email, code='')

Change account’s email address

Parameters:
  • password (str) – current account password
  • email (str) – new email address
  • code (str) – email code
Returns:

result

Return type:

EResult

Note

To change email, first call without code and then with, to finalize the change

change_password(password, new_password, email_code)

Change account’s password

Parameters:
  • password (str) – current account password
  • new_password (str) – new account password
  • email_code (str) – confirmation code from email
Returns:

result

Return type:

EResult

Note

First request change mail via request_password_change_mail() to get the email code

change_status(**kwargs)

Set name, persona state, flags

Note

Changing persona state will also change persona_state

Parameters:
  • persona_state (EPersonaState) – persona state (Online/Offlane/Away/etc)
  • player_name (str) – profile name
  • persona_state_flags (EPersonaStateFlag) – persona state flags
channel_hmac = None
channel_key = None
channel_secured = False
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
create_account(account_name, password, email='')

Create a new Steam account

Parameters:
  • account_name (str) – desired account name
  • password (str) – desired password
  • email (str) – desired email
Returns:

(EResult, SteamID)

Return type:

tuple

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)
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_app_ticket(app_id)

Get app ownership ticket

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

Get CDN authentication token

Parameters:
  • app_id (int) – app 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(depot_id, app_id=0)

Get depot decryption key

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

CMsgClientGetDepotDecryptionKeyResponse

Return type:

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_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: 'token', ...},
 'packages': {456: 'token', ...}
}
get_product_info(apps=[], packages=[], timeout=15)

Get product info for apps and packages

Parameters:
  • apps (list) – items in the list should be either just app_id, or (app_id, access_token)
  • packages (list) – items in the list should be either just package_id, or (package_id, access_token)
Returns:

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

Return type:

dict, None

{'apps':     {570: {...}, ...},
 'packages': {123: {...}, ...}
}
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

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 = <EPersonaState.Online: 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)
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_password_change_mail(password)

Request password change mail

Parameters:password (str) – current account password
Returns:result
Return type:EResult
request_persona_state(steam_ids, state_flags=863)

Request persona state data

Parameters:
request_validation_mail()

Request validation email

Returns:result
Return type:EResult
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)

Changed in version 0.8.4.

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)

Changed in version 0.8.4.

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)

Changed in version 0.8.4.

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)

Changed in version 0.8.4.

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

session_id = None
set_credential_location(path)

Sets folder location for sentry files

Needs to be set explicitly for sentries to be created.

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 – :class:`.EMsg’ or job 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