unifi-topology
Python library for UniFi network topology discovery and SVG diagram rendering.
Extracted from unifi-network-maps to provide a clean library API for programmatic use, including the Home Assistant integration.
Installation
pip install unifi-topology
Quick Start
from unifi_topology import (
Config,
SvgOptions,
build_node_type_map,
build_topology,
extract_wan_info,
fetch_devices,
fetch_networks,
normalize_devices,
render_svg,
resolve_svg_themes,
)
# Connect to UniFi controller
config = Config.from_env()
api_devices = fetch_devices(config)
networks = fetch_networks(config)
# Build topology model
devices = normalize_devices(api_devices)
node_types = build_node_type_map(devices)
gateways = [name for name, node_type in node_types.items() if node_type == "gateway"]
topology = build_topology(
devices,
include_ports=True,
only_unifi=False,
gateways=gateways,
)
gateway = next((device for device in devices if node_types.get(device.name) == "gateway"), None)
wan_info = extract_wan_info(gateway) if gateway else None
# Render SVG
theme = resolve_svg_themes(theme_name="unifi")
options = SvgOptions()
svg = render_svg(
topology.tree_edges or topology.raw_edges,
node_types=node_types,
theme=theme,
options=options,
wan_info=wan_info,
)
API Overview
Adapters
Config-- Configuration from environment variables (UNIFI_URL,UNIFI_USER/UNIFI_PASSorUNIFI_API_KEY, etc.)fetch_devices(config)-- Fetch device list from UniFi controllerfetch_clients(config)-- Fetch active clientsfetch_networks(config)-- Fetch network/VLAN configurationfetch_firewall_zones(config)-- Fetch firewall zone definitionsfetch_firewall_policies(config)-- Fetch zone-based firewall policiesfetch_firewall_groups(config)-- Fetch firewall address/port groupsresolve_hostnames(ips, dns_server)-- Reverse DNS resolution
Model
normalize_devices(raw)-- Convert raw API data toDeviceobjectsnormalize_firewall_zones(raw)-- Convert raw zone data toFirewallZoneobjectsnormalize_firewall_policies(raw)-- Convert raw policy data toFirewallPolicyobjectsnormalize_firewall_groups(raw)-- Convert raw group data toFirewallGroupobjectsbuild_node_type_map(devices, clients=None, ...)-- Classify node names for renderingbuild_topology(devices, *, include_ports, only_unifi, gateways)-- Build topology graph (TopologyResultwithraw_edgesandtree_edges)build_device_inventory(devices)-- Build device info table (list[DeviceInfo])extract_wan_info(device, ...)-- Extract WAN upstream info for a gateway device
Rendering
render_svg(edges, *, node_types, theme, options, ...)-- Orthogonal SVG diagramrender_svg_isometric(edges, *, node_types, theme, options, ...)-- Isometric 3D-style SVGrender_dual(edges, *, node_types, theme, options, ...)-- Physical + VLAN grouped SVG outputresolve_svg_themes(theme_name, theme_file)-- Load built-in or custom SVG theme
Built-in themes: unifi, unifi-dark, minimal, minimal-dark, classic,
classic-dark, blueprint (white line work on blueprint-blue paper --
monochrome outlines, white icons, graph-paper grid)
Isometric render options
render_svg_isometric has several refinements. The four listed first default
to off, so upgrading never changes an existing diagram -- turn on the ones you
want.
from unifi_topology.render.svg_theme import SvgOptions, SvgTheme, DEFAULT_THEME
import dataclasses
options = SvgOptions(
iso_compact_layout=True, # group devices instead of one long diagonal
iso_route_around_nodes=True, # route links around intervening devices
iso_lighting=True, # shaded side faces and contact shadows
iso_show_grid=False, # hide the isometric floor grid (on by default)
)
theme = dataclasses.replace(DEFAULT_THEME, icon_set="unifi")
svg = render_svg_isometric(edges, node_types=types, options=options, theme=theme)
| Option | Where | What it changes |
|---|---|---|
iso_compact_layout |
SvgOptions |
Packs each device and its clients into a block, and each block beneath its parent. The default maps sibling order to one grid axis and tree depth to the other; because home networks are shallow and wide, that draws everything along a single diagonal. On a 50-node network this takes the canvas from 11904x6892 to 5424x4397. Also guarantees one node per grid cell -- the default can place two devices on the same tile. |
iso_route_around_nodes |
SvgOptions |
Picks the link corner that crosses fewest devices, and steps into a clear lane when every simple route is blocked. Without it the corner is always taken on the same axis, so links are drawn over unrelated devices and their labels (20 of 31 links on that same network; 0 with it on). Legs stay grid-aligned either way, so they always project to true isometric lines. |
iso_lighting |
SvgOptions |
Shades each tile's side faces from its own colour under one light direction, and seats it with a contact shadow. |
icon_set |
SvgTheme |
isometric (default, isopacks artwork), modern, or unifi. |
iso_show_grid |
SvgOptions |
Draws the isometric floor grid behind the diagram. On by default -- set False for a plain background. Nothing else about the render changes, including the canvas size. |
Icon sets
| Set | Contents |
|---|---|
isometric |
Default. isopacks artwork (MIT). Generic rather than network-specific: access points are radio masts, NAS is a database cylinder, a client cluster is a person. Four subjects isopacks does not cover -- camera, speaker, games console, sensor -- are supplied from the unifi set, restyled into the isopacks palette. |
modern |
Flat icons with a per-type accent colour. |
unifi |
Original MIT artwork drawn for this project, one file per node type with no fallbacks. Devices look like the hardware they represent. Neutral grey-white bodies with a cyan accent -- a different visual family from isometric, so pick one rather than mixing. |
Rendered comparisons of each option live in docs/examples/.
Development
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
make lint # ruff check
make format # ruff format
make typecheck # pyright
make test # pytest
make ci # all checks
Contributing
See CONTRIBUTING.md for development setup and guidelines.
License
MIT -- see LICENSE. Third-party licenses in LICENSES.md.
Metadata
Release files for unifi-topology 3.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| unifi_topology-3.2.1.tar.gz | 518.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unifi_topology-3.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.1 MB
Release files / unifi_topology-3.2.1.tar.gz
| Download URL | unifi_topology-3.2.1.tar.gz |
|---|---|
| Size | 518.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ceec4ab7c7c9fad836d05bb850942e5f81940599b121324d3638cc9b00922572
|
|
BLAKE2b-256 checksum How to use checksums |
df17f3d82508fe00c207f8d06c862cb5bb14aeb2c294811785166cbefbf1f743
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency logRelease files / unifi_topology-3.2.1-py3-none-any.whl
| Download URL | unifi_topology-3.2.1-py3-none-any.whl |
|---|---|
| Size | 541.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a914ab5be47781486a542ea4841e0c7eddd6a0f5b5d9646b69286891f8dceb98
|
|
BLAKE2b-256 checksum How to use checksums |
ed1e00ae334a0382364e2654fa4786c22730c6f4b19eac81a94bbdef06dd649b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.
Transparency log