Complete, universal PHP client for Mikrotik RouterOS v6 API via Socket Protocol (Port 8728). Framework-agnostic with zero external dependencies.
- Universal API Client — Execute ANY RouterOS command, not just a pre-defined subset
- Dual-Mode Login — Auto-detects MD5 Challenge (pre-v6.43) and Plaintext (post-v6.43)
- Zero Dependencies — Only built-in PHP functions (
stream_socket_client,md5,chr,ord) - Framework-Agnostic — Works with PHP Native, Laravel, CodeIgniter, Symfony, or any PHP framework
- SSL Support — Connect via port 8729 with SSL encryption
- Auto-Retry — Configurable connection retry attempts with delay
- Auto-Parsing — Raw Mikrotik responses converted to structured PHP arrays
- PHP >= 8.2
- Network access to Mikrotik router on port 8728 (or 8729 for SSL)
composer require mivodev/mikrotik-api-ros6Use the Laravel wrapper instead, which provides ServiceProvider, Facade, and .env configuration:
composer require mivodev/laravel-mikrotik-api-ros6<?php
use Mivo\MikrotikRos6\Client;
$api = new Client();
$api->connect('192.168.1.1', 'admin', 'password');
// Get router identity
$identity = $api->comm('/system/identity/print');
print_r($identity);
$api->disconnect();use Mivo\MikrotikRos6\Client;
$api = new Client();
// Basic connection
$api->connect('192.168.1.1', 'admin', 'password');
// Custom port
$api->connect('192.168.1.1', 'admin', 'password', 8728);
// SSL connection (port 8729)
$api->ssl = true;
$api->connect('192.168.1.1', 'admin', 'password', 8729);$api = new Client();
$api->timeout = 3; // Connection timeout in seconds (default: 3)
$api->attempts = 5; // Number of retry attempts (default: 5)
$api->delay = 3; // Delay between retries in seconds (default: 3)
$api->ssl = false; // Use SSL connection (default: false)
$api->debug = false; // Enable debug output (default: false)The comm() method is the universal entry-point. It can execute any RouterOS command:
// ─── READ (print) ───────────────────────────────────
$users = $api->comm('/ip/hotspot/user/print');
$queues = $api->comm('/queue/simple/print');
$addrs = $api->comm('/ip/address/print');
$secrets = $api->comm('/ppp/secret/print');
$ifaces = $api->comm('/interface/print');
$firewall = $api->comm('/ip/firewall/filter/print');
$dns = $api->comm('/ip/dns/print');
$routes = $api->comm('/ip/route/print');
$resource = $api->comm('/system/resource/print');
// ─── CREATE (add) ───────────────────────────────────
$api->comm('/ip/hotspot/user/add', [
'name' => 'pelanggan-baru',
'password' => 'rahasia123',
'profile' => 'paket-50mbps',
]);
$api->comm('/ppp/secret/add', [
'name' => 'pppoe-user1',
'password' => 'secret',
'service' => 'pppoe',
'profile' => 'default',
]);
$api->comm('/queue/simple/add', [
'name' => 'queue-pelanggan',
'target' => '192.168.1.100/32',
'max-limit' => '10M/10M',
]);
// ─── UPDATE (set) ───────────────────────────────────
$api->comm('/ip/hotspot/user/set', [
'.id' => '*1',
'password' => 'password-baru',
]);
// ─── DELETE (remove) ────────────────────────────────
$api->comm('/ip/hotspot/user/remove', [
'.id' => '*1',
]);
// ─── SYSTEM OPERATIONS ─────────────────────────────
$api->comm('/system/reboot');
$api->comm('/system/identity/set', [
'name' => 'Router-Mivo',
]);Use the ? prefix on keys to filter results:
// Filter by exact value
$activeUsers = $api->comm('/ip/hotspot/active/print', [
'?user' => 'pelanggan-baru',
]);
// Filter PPPoE secrets by service type
$pppoeOnly = $api->comm('/ppp/secret/print', [
'?service' => 'pppoe',
]);
// Filter by profile
$premium = $api->comm('/ip/hotspot/user/print', [
'?profile' => 'paket-premium',
]);Use the ~ prefix for regex-based filtering:
// Find users whose name matches a pattern
$matched = $api->comm('/ip/hotspot/user/print', [
'~name' => 'pelanggan-.*',
]);All responses are returned as structured PHP arrays:
$users = $api->comm('/ip/hotspot/user/print');
// Returns:
// [
// ['.id' => '*1', 'name' => 'admin', 'profile' => 'default'],
// ['.id' => '*2', 'name' => 'pelanggan1', 'profile' => 'paket-50mbps'],
// ]
foreach ($users as $user) {
echo $user['name'] . ' — ' . $user['profile'] . "\n";
}use Mivo\MikrotikRos6\Client;
use Mivo\MikrotikRos6\Exceptions\MikrotikException;
$api = new Client();
try {
$api->connect('192.168.1.1', 'admin', 'wrong-password');
} catch (MikrotikException $e) {
echo "Connection failed: " . $e->getMessage();
}
try {
$result = $api->comm('/nonexistent/command');
} catch (MikrotikException $e) {
echo "Command failed: " . $e->getMessage();
}Enable debug mode to see all sent and received words:
$api = new Client();
$api->debug = true;
$api->connect('192.168.1.1', 'admin', 'password');
// Output:
// Connection attempt #1 to 192.168.1.1:8728...
// <<< [/login]
// <<< [=name=admin]
// <<< [=password=password]
// >>> [!done]
// Connected and authenticated.src/
├── Client.php # Main client — connect, disconnect, comm
├── Contracts/
│ └── ClientInterface.php # Universal interface (shared with ROS7)
├── Protocol/
│ ├── WordEncoder.php # Encode word length → binary prefix
│ ├── WordDecoder.php # Decode binary prefix → word from socket
│ └── Authenticator.php # Dual-mode login (MD5 + plaintext)
├── Parser/
│ └── ResponseParser.php # Raw socket words → PHP arrays
└── Exceptions/
└── MikrotikException.php # Structured error handling
This package was built using the following references:
- Mikrotik API Documentation (ROS7)
- Mikrotik API Documentation (ROS6 Legacy)
- Mikhmon v3 — routeros_api.class.php by Denis Basta & Laksamadi Guko
- EvilFreelancer/routeros-api-php
MIT License. See LICENSE for details.
