PHPackages                             0mithun/php-zkteco - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. 0mithun/php-zkteco

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

0mithun/php-zkteco
==================

A PHP package for managing ZKTeco biometric devices with TCP and UDP protocol support.

v1.3.5(4mo ago)2615MITPHPPHP ^8.0

Since Feb 17Pushed 4mo agoCompare

[ Source](https://github.com/0mithun/php-zkteco)[ Packagist](https://packagist.org/packages/0mithun/php-zkteco)[ Docs](https://github.com/0mithun/php-zkteco)[ RSS](/packages/0mithun-php-zkteco/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (1)Versions (13)Used By (0)

[![Zkteco Logo](logo.jpg)](https://www.zkteco.com/)

[![Latest Stable Version](https://camo.githubusercontent.com/f7d99f3137e6f56d3bf6d1f3ba8151ac1278a1b5e422883fe58a99e63e343ce3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f306d697468756e2f7068702d7a6b7465636f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/0mithun/php-zkteco)[![Total Downloads](https://camo.githubusercontent.com/1928b5573752edcaf1849e45c549cc62c27a7adf50efc79a02551ff06d16ba8f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f306d697468756e2f7068702d7a6b7465636f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/0mithun/php-zkteco)[![License](https://camo.githubusercontent.com/1cc8c25ad2e08e9353025d9097b038b4375803779c8ea61da0ca192e600b52b1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f306d697468756e2f7068702d7a6b7465636f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/0mithun/php-zkteco)

PHP ZKTeco
==========

[](#php-zkteco)

A PHP library for interfacing with ZKTeco biometric attendance devices. Supports both **TCP** and **UDP** protocols for reliable communication with fingerprint attendance machines.

Features
--------

[](#features)

- **Dual Protocol Support**: Works with both TCP and UDP connections
- **User Management**: Add, remove, and retrieve users from the device
- **Attendance Logs**: Fetch attendance records with optional filtering
- **Real-Time Logs**: 🆕 Listen for live attendance events as they happen
- **Fingerprint Management**: Get, set, and remove fingerprints
- **Device Control**: Enable/disable device, restart, shutdown, sleep/resume
- **LCD Display**: Write custom messages to device screen
- **Voice Test**: Play voice prompts on the device
- **Laravel Integration**: Auto-discovery service provider included

Requirements
------------

[](#requirements)

- PHP &gt;= 8.0
- PHP Sockets Extension (`ext-sockets`)

Installation
------------

[](#installation)

```
composer require 0mithun/php-zkteco
```

Quick Start
-----------

[](#quick-start)

```
use Mithun\PhpZkteco\Libs\ZKTeco;

// Create instance with TCP protocol (recommended for stability)
$zk = new ZKTeco('192.168.1.100', 4370, protocol: 'tcp');

// Or use UDP protocol (default)
$zk = new ZKTeco('192.168.1.100', 4370, protocol: 'udp');

// Connect to device
if ($zk->connect()) {
    // Get all users
    $users = $zk->getUsers();

    // Get attendance logs
    $attendance = $zk->getAttendances();

    // Disconnect when done
    $zk->disconnect();
}
```

TCPMUX HTTP CONNECT Proxy
-------------------------

[](#tcpmux-http-connect-proxy)

Connect through a TCPMUX httpconnect multiplexer for subdomain-based routing. This allows multiple devices to share a single port, routed by subdomain.

### Basic TCPMUX Usage

[](#basic-tcpmux-usage)

```
use Mithun\PhpZkteco\Libs\ZKTeco;

$zk = new ZKTeco(
    host: 'device-1.proxy.example.com',  // subdomain.base_domain
    port: 4370,  // ZKTeco device port (default)
    tcpmux: [
        'subdomain' => 'device-1',
        'port' => 1337,  // TCPMUX proxy port
    ]
);

if ($zk->connect()) {
    $users = $zk->getUsers();
    $zk->disconnect();
}
```

### How TCPMUX Works

[](#how-tcpmux-works)

1. Library connects to proxy server at `base_domain:tcpmux_port`
2. Sends HTTP CONNECT request with target `subdomain.base_domain:device_port`
3. Proxy routes the connection to the device based on subdomain
4. After tunnel is established, ZKTeco protocol communicates through it

### Connection Comparison

[](#connection-comparison)

FeatureDirect TCP/UDPTCPMUXPort per deviceRequired (e.g., 7001, 7002...)Shared (e.g., 1337)RoutingBy port numberBy subdomainScalabilityLimited by portsUnlimited subdomainsConstructor Parameters
----------------------

[](#constructor-parameters)

```
$zk = new ZKTeco(
    host: '192.168.1.100',     // Device IP/hostname (required)
    port: 4370,                // Device port (default: 4370)
    shouldPing: false,         // Ping before connecting (default: false)
    timeout: 25,               // Connection timeout in seconds (default: 25)
    password: 0,               // Device password/CMD key (default: 0)
    protocol: 'tcp',           // Protocol: 'tcp' or 'udp' (default: 'udp')
    tcpmux: []                 // TCPMUX config (optional, see below)
);

// TCPMUX configuration array:
$tcpmux = [
    'subdomain' => 'device-1', // Device subdomain for routing
    'port' => 1337,            // FRP TCPMUX port
];
```

---

API Reference
-------------

[](#api-reference)

### Connection Methods

[](#connection-methods)

#### `connect(): bool`

[](#connect-bool)

Establishes connection to the ZKTeco device.

```
$connected = $zk->connect();
if ($connected) {
    echo "Connected successfully!";
}
```

#### `disconnect(): bool`

[](#disconnect-bool)

Disconnects from the device.

```
$zk->disconnect();
```

#### `ping(bool $throw = false): bool`

[](#pingbool-throw--false-bool)

Tests connectivity to the device.

```
if ($zk->ping()) {
    echo "Device is reachable";
}
```

---

### Device Information Methods

[](#device-information-methods)

#### `vendorName(): string|false`

[](#vendorname-stringfalse)

Returns the device manufacturer name.

```
echo $zk->vendorName(); // "ZKTeco Inc."
```

#### `deviceName(): string|false`

[](#devicename-stringfalse)

Returns the device model name.

```
echo $zk->deviceName(); // "K40"
```

#### `deviceId(): string|false`

[](#deviceid-stringfalse)

Returns the device ID.

```
echo $zk->deviceId(); // "1"
```

#### `serialNumber(): string|false`

[](#serialnumber-stringfalse)

Returns the device serial number.

```
echo $zk->serialNumber(); // "PAS4234400018"
```

#### `version(): string|false`

[](#version-stringfalse)

Returns the firmware version.

```
echo $zk->version(); // "Ver 6.60 Apr 13 2022"
```

#### `osVersion(): string|false`

[](#osversion-stringfalse)

Returns the OS version.

```
echo $zk->osVersion(); // "1"
```

#### `platform(): string|false`

[](#platform-stringfalse)

Returns the platform information.

```
echo $zk->platform(); // "ZLM60_TFT"
```

#### `fmVersion(): string|false`

[](#fmversion-stringfalse)

Returns the firmware version number.

```
echo $zk->fmVersion(); // "10"
```

#### `pinWidth(): string|false`

[](#pinwidth-stringfalse)

Returns the PIN width setting.

```
echo $zk->pinWidth(); // "14"
```

#### `workCode(): string|false`

[](#workcode-stringfalse)

Returns the work code status.

```
echo $zk->workCode(); // "0"
```

#### `ssr(): string|false`

[](#ssr-stringfalse)

Returns the SSR (Self-Service Recorder) status.

```
echo $zk->ssr(); // "1"
```

#### `faceFunctionOn(): string|false`

[](#facefunctionon-stringfalse)

Returns whether face recognition is enabled.

```
echo $zk->faceFunctionOn(); // "0" or "1"
```

#### `getMemoryInfo(): object|false`

[](#getmemoryinfo-objectfalse)

Returns device memory information.

```
$memory = $zk->getMemoryInfo();
// Returns: {adminCounts, userCounts, userCapacity, logCounts, logCapacity}
```

---

### Time Methods

[](#time-methods)

#### `getTime(): string|false`

[](#gettime-stringfalse)

Returns the current device time.

```
echo $zk->getTime(); // "2026-02-17 12:30:00"
```

#### `setTime(string $time): bool`

[](#settimestring-time-bool)

Sets the device time.

```
$zk->setTime('2026-02-17 12:00:00');
```

---

### User Management Methods

[](#user-management-methods)

#### `getUsers(?callable $callback = null): array`

[](#getuserscallable-callback--null-array)

Retrieves all registered users from the device.

```
// Get all users
$users = $zk->getUsers();

// Each user contains:
// [
//     'uid' => 1,
//     'user_id' => '12345',
//     'name' => 'John Doe',
//     'role' => 0,
//     'password' => '1234',
//     'card_no' => '0000012345',
//     'device_ip' => '192.168.1.100'
// ]

// With filter callback
$admins = $zk->getUsers(function($user) {
    return $user['role'] == 14 ? $user : null;
});
```

#### `setUser(int $uid, string|int $userid, string $name, string|int $password, int $role = 0, int $cardno = 0): bool`

[](#setuserint-uid-stringint-userid-string-name-stringint-password-int-role--0-int-cardno--0-bool)

Adds or updates a user on the device.

**Parameters:**

- `$uid` - Unique ID (1-65535)
- `$userid` - User ID string (max 9 chars)
- `$name` - User name (max 24 chars)
- `$password` - Password (max 8 chars)
- `$role` - Role: 0=User, 14=Admin (default: 0)
- `$cardno` - Card number (default: 0)

```
// Add a regular user
$zk->setUser(1, '10001', 'John Doe', '1234', 0, 0);

// Add an admin user
$zk->setUser(2, '10002', 'Admin User', '5678', 14, 0);
```

#### `removeUser(int $uid): bool`

[](#removeuserint-uid-bool)

Removes a user by UID.

```
$zk->removeUser(1);
```

#### `deleteUsers(callable $callback): void`

[](#deleteuserscallable-callback-void)

Removes users conditionally using a callback.

```
// Delete all users with role 0
$zk->deleteUsers(function($user) {
    return $user['role'] == 0;
});
```

#### `clearAllUsers(): bool`

[](#clearallusers-bool)

⚠️ **Warning:** Removes ALL users from the device.

```
$zk->clearAllUsers();
```

#### `clearAdminPriv(): bool`

[](#clearadminpriv-bool)

Removes admin privileges from all users.

```
$zk->clearAdminPriv();
```

---

### Attendance Methods

[](#attendance-methods)

#### `getAttendances(?callable $callback = null): array`

[](#getattendancescallable-callback--null-array)

Retrieves attendance records from the device.

```
// Get all attendance records
$logs = $zk->getAttendances();

// Each record contains:
// [
//     'uid' => 1,
//     'user_id' => 12345,
//     'state' => 1,
//     'record_time' => '2026-02-17 09:00:00',
//     'type' => 0,
//     'device_ip' => '192.168.1.100'
// ]

// With filter callback (e.g., today's records only)
$todayLogs = $zk->getAttendances(function($record) {
    if (str_starts_with($record['record_time'], date('Y-m-d'))) {
        return $record;
    }
    return null;
});
```

**Attendance States:**

- `0` - Check In
- `1` - Check Out
- `2` - Break Out
- `3` - Break In
- `4` - OT In
- `5` - OT Out

#### `clearAttendance(): bool`

[](#clearattendance-bool)

⚠️ **Warning:** Clears ALL attendance logs from the device.

```
$zk->clearAttendance();
```

#### `getRealTimeLogs(callable $callback, int $timeout = 0): bool`

[](#getrealtimelogscallable-callback-int-timeout--0-bool)

🆕 Registers for real-time attendance events. When a user scans their fingerprint or enters credentials, the callback is called immediately with the log data.

**Parameters:**

- `$callback` - Function called with each real-time log entry
- `$timeout` - Timeout in seconds (0 = infinite, default)

```
// Listen for real-time attendance events
$zk->getRealTimeLogs(function($log) {
    echo "User {$log['user_id']} punched at {$log['record_time']}\n";

    // $log contains:
    // [
    //     'user_id' => '12345',
    //     'record_time' => '2026-02-17 09:00:00',
    //     'state' => 1,
    //     'device_ip' => '192.168.1.100'
    // ]
}, timeout: 60); // Listen for 60 seconds

// Or listen indefinitely (Ctrl+C to stop)
$zk->getRealTimeLogs(function($log) {
    // Process attendance in real-time
    saveToDatabase($log);
});
```

**Note:** This method blocks while listening for events. Use the `$timeout` parameter or run in a background process/worker.

#### `getRealTimeEvents(callable $callback, int $events, int $timeout = 0): bool`

[](#getrealtimeeventscallable-callback-int-events-int-timeout--0-bool)

🆕 **v1.2.0** Registers for multiple real-time event types. This is a more comprehensive version of `getRealTimeLogs()` that supports all device events.

**Supported Events (use `Mithun\PhpZkteco\Libs\Services\Util` constants):**

ConstantValueDescription`EF_ATTLOG`1Attendance log (user punch in/out)`EF_FINGER`2Fingerprint scanned`EF_ENROLLUSER`4User enrolled on device`EF_ENROLLFINGER`8Fingerprint enrolled`EF_BUTTON`16Button pressed on device`EF_UNLOCK`32Door unlocked`EF_VERIFY`128User verified`EF_FPFTR`256Fingerprint feature event`EF_ALARM`512Alarm triggered**Parameters:**

- `$callback` - Function called with each event
- `$events` - Bitmask of events to listen for (combine with `|`)
- `$timeout` - Timeout in seconds (0 = infinite)

```
use Mithun\PhpZkteco\Libs\Services\Util;

// Listen for attendance AND user enrollment events
$events = Util::EF_ATTLOG | Util::EF_ENROLLUSER | Util::EF_ENROLLFINGER;

$zk->getRealTimeEvents(function($event) {
    echo "Event: {$event['event_name']}\n";

    switch ($event['event_type']) {
        case Util::EF_ATTLOG:
            echo "Attendance: User {$event['user_id']} at {$event['record_time']}\n";
            break;

        case Util::EF_ENROLLUSER:
            echo "New user enrolled: {$event['user_id']}\n";
            break;

        case Util::EF_ENROLLFINGER:
            echo "Fingerprint enrolled for user {$event['user_id']}, finger {$event['finger_index']}\n";
            break;

        case Util::EF_UNLOCK:
            echo "Door {$event['door_id']} unlocked\n";
            break;

        case Util::EF_ALARM:
            echo "Alarm triggered: type {$event['alarm_type']}\n";
            break;
    }
}, $events, timeout: 3600); // Listen for 1 hour
```

**Event Data Structure:**

All events include these base fields:

```
[
    'event_type' => 1,              // Event constant (EF_ATTLOG, etc.)
    'event_name' => 'attendance',   // Human-readable name
    'device_ip' => '192.168.1.100',
    'timestamp' => '2026-02-17 09:00:00',
]
```

Plus event-specific fields:

EventAdditional Fields`EF_ATTLOG``user_id`, `record_time`, `state``EF_ENROLLUSER` / `EF_VERIFY``user_id``EF_FINGER` / `EF_ENROLLFINGER` / `EF_FPFTR``user_id`, `finger_index``EF_BUTTON``button_id``EF_UNLOCK``door_id`, `unlock_type``EF_ALARM``alarm_type`---

### Fingerprint Methods

[](#fingerprint-methods)

#### `getFingerprint(int $uid): array|false`

[](#getfingerprintint-uid-arrayfalse)

Retrieves fingerprint data for a user.

```
$fingerprints = $zk->getFingerprint(1);
// Returns array of fingerprint templates indexed by finger ID (0-9)
```

#### `setFingerprint(int $uid, array $fingerprint): bool`

[](#setfingerprintint-uid-array-fingerprint-bool)

Sets fingerprint data for a user.

```
$zk->setFingerprint(1, $fingerprintData);
```

#### `removeFingerprint(int $uid, array $fingerIds): int`

[](#removefingerprintint-uid-array-fingerids-int)

Removes specific fingerprints from a user.

```
// Remove fingerprints 0 and 1 from user with UID 1
$deleted = $zk->removeFingerprint(1, [0, 1]);
echo "Deleted $deleted fingerprints";
```

---

### Device Control Methods

[](#device-control-methods)

#### `disableDevice(): bool`

[](#disabledevice-bool)

Disables the device (prevents user interaction).

```
$zk->disableDevice();
// Device screen shows "Working..." and ignores user input
```

#### `enableDevice(): bool`

[](#enabledevice-bool)

Re-enables the device.

```
$zk->enableDevice();
```

#### `shutdown(): bool`

[](#shutdown-bool)

Powers off the device.

```
$zk->shutdown();
```

#### `restart(): bool`

[](#restart-bool)

Restarts the device.

```
$zk->restart();
```

#### `sleep(): bool`

[](#sleep-bool)

Puts the device into sleep mode.

```
$zk->sleep();
```

#### `resume(): bool`

[](#resume-bool)

Wakes the device from sleep mode.

```
$zk->resume();
```

---

### Display &amp; Audio Methods

[](#display--audio-methods)

#### `writeLCD(string $message = 'Welcome ZkTeco'): bool`

[](#writelcdstring-message--welcome-zkteco-bool)

Displays a message on the device LCD screen.

```
$zk->writeLCD('Hello World!');
```

#### `clearLCD(): bool`

[](#clearlcd-bool)

Clears the LCD screen.

```
$zk->clearLCD();
```

#### `testVoice(int $index = 0): bool`

[](#testvoiceint-index--0-bool)

Plays a voice prompt on the device.

```
$zk->testVoice(0);  // Play voice prompt index 0

// Common voice indices:
// 0 - "Thank you"
// 1 - "Incorrect fingerprint"
// 4 - "Thank you"
```

---

### Custom Data Methods

[](#custom-data-methods)

#### `getDeviceData(string $key): string`

[](#getdevicedatastring-key-string)

Retrieves device configuration data.

```
echo $zk->getDeviceData('TCPPort');     // "4370"
echo $zk->getDeviceData('DeviceID');    // "1"
```

#### `setCustomData(string $key, mixed $value): bool`

[](#setcustomdatastring-key-mixed-value-bool)

Sets custom data on the device.

```
$zk->setCustomData('my_company', 'Acme Corp');
```

#### `getCustomData(string $key): string`

[](#getcustomdatastring-key-string)

Retrieves custom data from the device.

```
echo $zk->getCustomData('my_company'); // "Acme Corp"
```

#### `setPushCommKey(string $value): bool`

[](#setpushcommkeystring-value-bool)

Sets the push communication key (for iClock integration).

```
$zk->setPushCommKey('my_secret_key');
```

#### `getPushCommKey(): string`

[](#getpushcommkey-string)

Gets the push communication key.

```
echo $zk->getPushCommKey();
```

---

Protocol Comparison
-------------------

[](#protocol-comparison)

FeatureTCPUDPReliabilityHighMediumSpeedSlightly slowerFastConnectionPersistentConnectionlessLarge data transferBetterMay have issuesRecommended forProductionLocal testingError Handling
--------------

[](#error-handling)

```
try {
    $zk = new ZKTeco('192.168.1.100', 4370, protocol: 'tcp');

    if (!$zk->connect()) {
        throw new Exception('Failed to connect to device');
    }

    $users = $zk->getUsers();

    $zk->disconnect();

} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}
```

Laravel Usage
-------------

[](#laravel-usage)

The package auto-registers its service provider. You can use it in your controllers or commands:

```
use Mithun\PhpZkteco\Libs\ZKTeco;

class AttendanceController extends Controller
{
    public function sync()
    {
        $zk = new ZKTeco(
            config('zkteco.ip'),
            config('zkteco.port'),
            protocol: config('zkteco.protocol', 'tcp')
        );

        if ($zk->connect()) {
            $attendances = $zk->getAttendances();

            foreach ($attendances as $record) {
                // Save to database
                Attendance::updateOrCreate(
                    ['uid' => $record['uid'], 'record_time' => $record['record_time']],
                    $record
                );
            }

            $zk->disconnect();
        }

        return response()->json(['synced' => count($attendances)]);
    }
}
```

Debugging
---------

[](#debugging)

Enable debug logging by defining constants before instantiation:

```
define('ZKTECO_DEBUG', true);
define('ZKTECO_DEBUG_LOG', '/path/to/debug.log');

$zk = new ZKTeco('192.168.1.100', 4370, protocol: 'tcp');
```

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](https://github.com/0mithun/php-zkteco/graphs/contributors) for details.

Security
--------

[](#security)

If you've found a security vulnerability, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Mithun](https://github.com/0mithun)
- [ZK Protocol Documentation](https://github.com/adrobinoga/zk-protocol)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance75

Regular maintenance activity

Popularity21

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

12

Last Release

135d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/43243086?v=4)[Mithun Halder](/maintainers/0mithun)[@0mithun](https://github.com/0mithun)

---

Top Contributors

[![0mithun](https://avatars.githubusercontent.com/u/43243086?v=4)](https://github.com/0mithun "0mithun (17 commits)")

---

Tags

laraveltcpudpFingerprintzktecoattendancesbiometric

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/0mithun-php-zkteco/health.svg)

```
[![Health](https://phpackages.com/badges/0mithun-php-zkteco/health.svg)](https://phpackages.com/packages/0mithun-php-zkteco)
```

###  Alternatives

[hhxsv5/laravel-s

🚀 LaravelS is an out-of-the-box adapter between Laravel/Lumen and Swoole.

3.9k691.5k13](/packages/hhxsv5-laravel-s)[coding-libs/zkteco-php

A package for managing ZKTeco device.

194.8k](/packages/coding-libs-zkteco-php)[mehedijaman/laravel-zkteco

Connect any zkteco fingerprint attendance machine to laravel application with no effort.

514.9k](/packages/mehedijaman-laravel-zkteco)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
