orbnet provides a simple, async Python interface to the Orb Local API and Datasets, allowing you to easily retrieve comprehensive network quality metrics from your Orb sensors.
Orb is an intelligent network monitoring platform that continuously measures internet experience. Unlike traditional speed tests that provide only momentary snapshots, Orb gives you real-time insights into your network's responsiveness, reliability, and speed.
- Async/await support - Built on
httpxfor efficient concurrent requests - Type safety - Pydantic models for data validation
- Multiple granularities - 1-second, 15-second, and 1-minute data buckets
- Polling support - Automatically fetch only new records
- Flexible formats - JSON or JSONL output
- Comprehensive datasets - Scores, responsiveness, web performance, speed tests, and Wi-Fi link metrics
pip install orbnetOr using uv:
uv add orbnet- Install Orb on your machine of choice
- Enable Local API access
import asyncio
from orbnet import OrbAPIClient
async def main():
# Connect to your Orb sensor
client = OrbAPIClient(host="192.168.0.20", port=7080)
# Get the latest network quality scores
scores = await client.get_scores_1m()
if scores:
latest = scores[-1]
print(f"Orb Score: {latest['orb_score']:.0f}")
print(f"Responsiveness: {latest['responsiveness_score']:.0f}")
print(f"Reliability: {latest['reliability_score']:.0f}")
print(f"Speed: {latest['speed_score']:.0f}")
asyncio.run(main())Orb Score: 93
Responsiveness: 91
Reliability: 100
Speed: 95
from orbnet import OrbAPIClient
client = OrbAPIClient(host="192.168.0.20")
# Get 1-minute scores
scores = await client.get_scores_1m()
# Get responsiveness data (1s, 15s, or 1m granularity)
responsiveness = await client.get_responsiveness(granularity="1s")
# Get web responsiveness (TTFB and DNS)
web_data = await client.get_web_responsiveness()
# Get speed test results
speeds = await client.get_speed_results()
# Get Wi-Fi link metrics (signal strength, SNR, link rates)
wifi_data = await client.get_wifi_link(granularity="1m")
# Get all datasets at once
all_data = await client.get_all_datasets()Monitor your network continuously with automatic polling:
async def monitor_network():
client = OrbAPIClient(host="192.168.0.20")
# Poll for new data every 10 seconds
async for records in client.poll_dataset(
dataset_name="responsiveness_1s",
interval=10.0
):
if records:
latest = records[-1]
latency_ms = latest['latency_avg_us'] / 1000
print(f"Latency: {latency_ms:.1f}ms")def alert_callback(dataset_name, records):
for record in records:
# Alert on high latency
if record['latency_avg_us'] > 50000: # 50ms
print(f"⚠️ High latency: {record['latency_avg_us']}μs")
# Alert on packet loss
if record['packet_loss_pct'] > 1.0: # 1%
print(f"⚠️ Packet loss: {record['packet_loss_pct']:.2f}%")
async def monitor_with_alerts():
client = OrbAPIClient(host="192.168.0.20")
async for _ in client.poll_dataset(
dataset_name="responsiveness_1s",
interval=5.0,
callback=alert_callback
):
pass # Callback handles alertsasync def analyze_speeds():
client = OrbAPIClient(host="192.168.0.20")
speeds = await client.get_speed_results()
# Convert to Mbps and calculate statistics
downloads = [s['download_kbps'] / 1000 for s in speeds]
avg_speed = sum(downloads) / len(downloads)
min_speed = min(downloads)
max_speed = max(downloads)
print(f"Download Speed Stats:")
print(f" Average: {avg_speed:.1f} Mbps")
print(f" Minimum: {min_speed:.1f} Mbps")
print(f" Maximum: {max_speed:.1f} Mbps")
# Check SLA compliance
required_mbps = 100
below_sla = [s for s in downloads if s < required_mbps]
if below_sla:
pct_below = (len(below_sla) / len(downloads)) * 100
print(f"⚠️ {pct_below:.1f}% of tests below {required_mbps} Mbps")async def compare_by_isp():
client = OrbAPIClient(host="192.168.0.20")
scores = await client.get_scores_1m()
# Group scores by ISP
isp_scores = {}
for record in scores:
isp = record['isp_name']
if isp not in isp_scores:
isp_scores[isp] = []
isp_scores[isp].append(record['orb_score'])
# Calculate averages
for isp, scores_list in isp_scores.items():
avg = sum(scores_list) / len(scores_list)
print(f"{isp}: {avg:.1f}/100")Overall network quality scores and component metrics (1-minute minimum granularity):
orb_score- Overall quality score (0-100)responsiveness_score- Network responsiveness (0-100)reliability_score- Connection reliability (0-100)speed_score- Bandwidth score (0-100)- Plus underlying measures: lag, download/upload speeds, etc.
Detailed responsiveness metrics at 1-second, 15-second, or 1-minute granularity:
lag_avg_us- Average lag in microsecondslatency_avg_us- Round-trip latency in microsecondsjitter_avg_us- Jitter (latency variation) in microsecondspacket_loss_pct- Packet loss percentage- Router-specific metrics for local network analysis
Web browsing experience metrics (once per minute):
ttfb_us- Time to First Byte in microsecondsdns_us- DNS resolution time in microsecondsweb_url- URL being tested
Speed test results (once per hour by default):
download_kbps- Download speed in Kbpsupload_kbps- Upload speed in Kbpsspeed_test_server- Server used for testingspeed_test_engine- Testing engine (Orb or iperf)
Signal quality and link-layer metrics for the active Wi-Fi connection at 1-second, 15-second, or 1-minute granularity:
rssi_avg— Average received signal strength in dBm (e.g., -55 is good; below -75 is poor)snr_avg— Average signal-to-noise ratio in dB (higher is better)noise_avg— Average background RF noise level in dBmtx_rate_mbps— Average transmit link rate in Mbpsrx_rate_mbps— Average receive link rate in Mbps (not available on macOS)phy_mode— Wi-Fi standard (e.g.,802.11ac,802.11ax)channel_band— Band (e.g.,2.4 GHz,5 GHz)channel_number/frequency_mhz— Channel and frequencysecurity— Security protocol (not available on Android)bssid/network_name— Access point MAC and SSID
Platform notes: Not available on iOS or ethernet-connected Orbs.
mcsandnss(modulation/coding scheme, spatial streams) are Linux only.
wifi_data = await client.get_wifi_link(granularity="1m")
if wifi_data:
latest = wifi_data[-1]
print(f"Signal: {latest.rssi_avg:.1f} dBm, SNR: {latest.snr_avg:.1f} dB")
print(f"Link rate: {latest.tx_rate_mbps:.0f} Mbps ({latest.phy_mode})")
if latest.rssi_avg < -75:
print("Weak signal — consider moving closer to the access point")client = OrbAPIClient(
host="192.168.0.20", # Orb sensor IP/hostname
port=7080, # API port (default: 7080)
caller_id="my-app", # Persistent ID for polling
client_id="MyApp/1.0.0", # User-Agent identifier
timeout=30.0, # Request timeout in seconds
)The caller_id parameter enables stateful polling - the Orb sensor tracks which records each caller has already received, returning only new data on subsequent requests. This is perfect for building real-time monitoring systems.
# First request returns all available data
client = OrbAPIClient(host="192.168.0.20", caller_id="monitor-1")
data1 = await client.get_scores_1m() # Returns: 100 records
# Second request returns only new data
data2 = await client.get_scores_1m() # Returns: 5 new recordsThe client_id is sent as the User-Agent header and helps identify your application in Orb sensor logs:
# Development
client = OrbAPIClient(
host="192.168.0.20",
client_id="MyApp/dev-0.1.0"
)
# Production with metadata
client = OrbAPIClient(
host="192.168.0.20",
client_id="MyApp/1.0.0 (production; host=server-01)"
)-
get_scores_1m(format="json", caller_id=None)
Retrieve 1-minute granularity Scores dataset -
get_responsiveness(granularity="1m", format="json", caller_id=None)
Retrieve Responsiveness dataset (1s, 15s, or 1m) -
get_web_responsiveness(format="json", caller_id=None)
Retrieve Web Responsiveness dataset -
get_speed_results(format="json", caller_id=None)
Retrieve Speed test results -
get_wifi_link(granularity="1m", caller_id=None)Retrieve Wi-Fi Link dataset (1s, 15s, or 1m) -
get_all_datasets(format="json", caller_id=None, include_all_responsiveness=False)Retrieve all datasets concurrently -
poll_dataset(dataset_name, interval=60.0, format="json", callback=None, max_iterations=None)
Continuously poll a dataset at regular intervals
host- Configured hostport- Configured portcaller_id- Configured caller IDclient_id- Configured client IDtimeout- Request timeout
Returns a Python list of dictionaries:
scores = await client.get_scores_1m(format="json")
# Returns: [{"orb_score": 85.5, ...}, {"orb_score": 87.2, ...}]Returns newline-delimited JSON as a string, useful for streaming:
scores = await client.get_scores_1m(format="jsonl")
# Returns: '{"orb_score": 85.5, ...}\n{"orb_score": 87.2, ...}\n'
# Parse it:
import json
for line in scores.strip().split('\n'):
record = json.loads(line)
print(record['orb_score'])import httpx
try:
client = OrbAPIClient(host="192.168.0.20", timeout=5.0)
scores = await client.get_scores_1m()
except httpx.ConnectError:
print("Unable to connect to Orb sensor")
except httpx.TimeoutException:
print("Request timed out")
except httpx.HTTPStatusError as e:
print(f"HTTP error: {e.response.status_code}")orbnet includes a Model Context Protocol (MCP) server that allows Claude and other LLM applications to access your Orb network data.
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"orb-net": {
"command": "uvx",
"args": [
"--from",
"orbnet[mcp]",
"orbnet-mcp"
],
"env": {
"ORB_HOST": "<host IP address>",
"ORB_PORT": "7080"
}
}
}
}This project is licensed under the MIT License - see the LICENSE file for details.
This is an unofficial client library and is not officially affiliated with Orb. For official support, visit orb.net.