A Python API for the configuration of TP-Link IP cameras. Can be used to automate changing any setting of the camera that the camera's web UI shows (except user/password management).
Warning
This is a barebones API. If you want to add support for more of the camera's settings, you will need to use devtools to find the API paths to change those settings, then define them in api.py.
Tested with the TP-Link VIGI C350.
Because I thought it would be fun to reverse engineer the web UI's authentication flow. It turned out to be annoyingly easy, since the code is simple and not obfuscated. Regardless, I made it into a basic API in case someone wanted it.
It makes requests in the same way that the camera's web UI does, basically.
Documentation of how the authentication works.
| Field | Description |
|---|---|
base_url |
A (HTTPS) URL to the camera's web UI |
username |
The username for authentication |
password |
The password for authentication |
You also need a salt for RSA encryption. In my case, it was just hardcoded into the class.js > Tool.md5AuthPwd function.
impl: TPLinkIPCClient._fetch_encryption_info
-
Send a POST request to
base_urlBody:
{ "method": "do", "user_management": { "get_encrypt_info": None } }Response fields:
Field Type Description codeintAn error code encrypt_typelist[str]The device's supported encryption types keystrRSA public key for encrypting the password noncestrA nonce value passwdTypestrAlways "md5" in my tests; not used by the web interface Note: This endpoint returns status code 401 and a non-zero
codedespite allowing access. -
Un-URL-quote
key, then convert to PEM format →pubkey_pem -
Determine which encryption type to use from
encrypt_type→encrypt_type
impl: TPLinkIPCClient.login
- MD5 hash
{password}{salt}→pwd_md5 - Encrypt password:
- If
encrypt_typeis RSA:- RSA encrypt
{pwd_md5}:{nonce}with keypubkey_pem→encrypted_pwd
- RSA encrypt
- Otherwise:
- Use
pwd_md5asencrypted_pwd
- Use
- If
- URL-quote
encrypted_pwd→encrypted_pwd
impl: TPLinkIPCClient.login
-
Send a POST request to
base_urlBody:
{ "method": "do", "login": { "username": username, "password": encrypted_pwd, "passwdType": "md5", "encrypt_type": encrypt_type } }Note:
"md5"is hardcoded aspasswdTypebecause it was hardcoded in the web UI's code. Perhaps previous firmware versions used MD5 for authentication?Response fields:
Field Type Description error_codeintAn error code stokstrThe session token
To use the token, send a request to {base_url}/stok={stok}/ds with whatever body is necessary to get or set the target setting.
- My camera uses the
TLS_RSA_WITH_AES_256_GCM_SHA384on TLS 1.2. I had to configure the code to use this cipher, as it was not permitted for TLS 1.2 by default (due to it being old). - You can access an emulated web UI of some cameras here; though it doesn't emulate almost any of the web requests that this project relies on.