ZKTeco Python SDK (zk-sdk)
A production-ready, type-hinted, synchronous and asynchronous Python SDK for ZKTeco standalone access control and time attendance devices (Bio Inox Plus, iFace, K-Series, IN01, etc.) built on top of pyzk and pydantic v2.
Highlights
- 🔄 Dual Engine: High-level synchronous (
ZKClient) and asynchronous non-blocking (AsyncZKClient) interfaces. - 🔒 Device Safety: Keypad and display locking during sensitive operations (
_device_locked) to prevent race conditions. - 🛡️ Pydantic v2 Type Safety: Strict data models (
User,FingerprintTemplate,AttendanceRecord,DeviceInfo,CapacityInfo). - 👤 Full User Management: Create, update, delete, list, filter by department (
group_id), and search by RFID card. - 👆 Biometrics (Fingerprints): Read, write, delete templates, remote enrollment, user backup, and High-Rate bulk restore (
HR_save_usertemplates). - ⚡️ Real-Time Live Capture: Real-time event streaming with background worker threads and async coroutine dispatch.
- ⏰ Software Access Rules: Integrated logical Access Rules engine (
AccessRulesRegistry,TimeWindow,TimeZoneRule,Area) with JSON persistence to evaluate live access events in software. - 🚪 Relay & Hardware Actions: Remote door unlocking, audio voice test prompts, device restart, poweroff, and memory clearing.
Installation
pip install zk-sdk
Or install with development dependencies:
pip install zk-sdk[dev]
Quick Start
Synchronous Usage (ZKClient)
from zk_sdk import ZKClient
# Automatic connection and cleanup using context manager
with ZKClient("192.168.1.201", port=4370, timeout=10, force_udp=True) as client:
# 1. Device Info
info = client.get_info()
print(f"Connected to {info.platform} - Firmware: {info.firmware_version}")
# 2. List Users
users = client.list_users()
print(f"Total registered users: {len(users)}")
for user in users:
print(f"UID={user.uid} | ID={user.user_id} | Name={user.name} | Dept={user.group_id}")
# 3. Add or update user
client.add_user(
uid=101,
user_id="101",
name="John Doe",
password="123",
card=987654,
department="Engineering",
)
# 4. Pulse Relay (Unlock door for 5 seconds)
client.unlock_door(seconds=5)
Asynchronous Usage (AsyncZKClient)
For modern async frameworks (FastAPI, aio-pika, UniHub, Celery async):
import asyncio
from zk_sdk import AsyncZKClient
async def main():
async with AsyncZKClient("192.168.1.201") as client:
# Get memory capacity
cap = await client.get_capacity()
print(f"Users: {cap.users}/{cap.users_cap} | Fingers: {cap.fingers}/{cap.fingers_cap}")
# Fetch attendance logs
logs = await client.get_attendance(limit=10)
for log in logs:
print(f"User: {log.user_id} at {log.timestamp} (Punch: {log.punch})")
if __name__ == "__main__":
asyncio.run(main())
Key Capabilities
1. Biometrics & Fingerprint Templates
with ZKClient("192.168.1.201") as client:
# Read all stored templates
templates = client.get_all_templates()
print(f"Found {len(templates)} biometric templates.")
# Backup a user and their enrolled templates
user, user_templates = client.backup_user_with_templates(uid=101)
# Remote enrollment (device prompts the user to place finger on sensor)
success = client.enroll_user(uid=101, temp_id=0)
if success:
print("Fingerprint enrolled successfully!")
# Delete single fingerprint template (finger 0) without removing the user
client.delete_user_template(uid=101, temp_id=0)
2. Real-Time Live Capture & Logical Access Rules
Standalone ZKTeco devices do not enforce complex time schedules natively on hardware. The SDK provides an in-software rules registry to evaluate punches in real-time:
from zk_sdk import ZKClient, AccessRulesRegistry
# Define rules
rules = AccessRulesRegistry(storage_path="access_rules.json")
rules.define_time_zone("Commercial", [(None, "08:00", "18:00")]) # Daily 8h - 18h
rules.define_area("Office", time_zone="Commercial")
rules.assign_user_to_area(user_id="101", area_name="Office")
rules.save()
# Start live capture with rule enforcement
with ZKClient("192.168.1.201", rules=rules) as client:
def on_event(event):
print(f"Punch from {event.attendance.user_id}: Allowed={event.allowed} ({event.verdict})")
client.watch_live_events(on_event=on_event, enforce_rules=True)
3. Hardware Controls & Audio
with ZKClient("192.168.1.201") as client:
# Unlock door relay for 3 seconds
client.unlock_door(seconds=3)
# Play voice message (0 = "Thank you", 2 = "Access denied")
client.test_voice(index=0)
# Synchronize terminal clock with system time
client.sync_time()
# Reboot terminal
client.restart_device()
Architecture & Compatibility
- Protocol: Standalone UDP/TCP ZK Protocol (port 4370) via
pyzk. - Concurrency:
AsyncZKClientexecutes synchronous pyzk calls safely viaasyncio.to_threadwith mutual exclusion locking. - Legacy Compatibility:
ZKAdapteris provided as an alias forZKClientfor seamless drop-in compatibility with legacy scripts.
License
MIT License - Tsuriu Tech / AccessHub.
Metadata
Release files for zk-sdk 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| zk_sdk-0.1.0.tar.gz | 23.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| zk_sdk-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.9 kB
Release files / zk_sdk-0.1.0.tar.gz
| Download URL | zk_sdk-0.1.0.tar.gz |
|---|---|
| Size | 23.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c74607cd09b521f12367267aa6647f5295316bd67dcab5f6f3244e76fabc73aa
|
|
BLAKE2b-256 checksum How to use checksums |
8efbfecbb95a647c7c7d845156b61d23a0f14fe827e567f355d2641070b8a944
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.5
|
Release files / zk_sdk-0.1.0-py3-none-any.whl
| Download URL | zk_sdk-0.1.0-py3-none-any.whl |
|---|---|
| Size | 20.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
89945f664ac38aec0c929baf51c3e239df86292f89570fffe6ee12a39c6e62ec
|
|
BLAKE2b-256 checksum How to use checksums |
99077d2abb34d9caf6a4ce0826c0e425148a233381e7fdc21c08fb5c717a7720
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.5
|