MIB Viewer

Using the API

Last updated September 10, 2026

Everything the MIB Viewer interface does - looking up an OID, browsing a MIB, searching - goes through a small set of JSON endpoints under api/. Nothing here is private or internal-only; this page documents them so you can script against the same data the site uses.

Looking up a single OID

GET api/tree.php?node=<oid>

Returns that object's full detail plus its immediate children in one round trip:

curl "https://mib-viewer.com/api/tree.php?node=1.3.6.1.2.1.1.1.0"
{
  "node": {
    "oid": "1.3.6.1.2.1.1.1.0",
    "parentOid": "1.3.6.1.2.1.1",
    "arc": 1,
    "name": "sysDescr",
    "kind": "OBJECT-TYPE",
    "description": "A textual description of the entity...",
    "syntax": "DisplayString (SIZE (0..255))",
    "access": "read-only",
    "status": "current",
    "sourceFile": "SNMPv2-MIB",
    "sourceMibId": 42
  },
  "children": [],
  "childCount": 0
}

A 404 with {"error": "Not found"} means that exact OID isn't in the database - not necessarily that it's wrong, since a real device may return values under OIDs (table rows, for instance) that only the base object is recorded under here.

Walking a subtree

GET api/tree.php?parent=<oid>

Returns just the direct children of a node - useful for walking a tree one level at a time without pulling each node's full description/syntax, which ?node= would also fetch.

Searching

GET api/tree.php?search=<term>&scope=objects|mibs

scope=objects (the default) matches OIDs and object names - a numeric term like 1.3.6.1.4.1.9 is treated as an OID prefix and returns matches nested under it; anything else is matched against object names. scope=mibs searches MIB file and module names only. Neither scope searches description text - see the Searching OIDs guide for why, and how to search descriptions when you need to.

Resolving a MIB name to an ID

GET api/tree.php?findModule=<exact module name>

Most of the API is OID- or ID-based, since a module name isn't guaranteed unique the way a numeric ID is. This endpoint covers the case where you only have a name: {"found": true, "mibId": 42}, or {"found": false} if nothing matches exactly - it does not do fuzzy matching, use ?search=&scope=mibs for that.

Fetching a whole MIB

GET api/tree.php?mib=<numeric id>

Returns every object the module defines, its type definitions, and its import groups - the same payload the MIB view itself renders from. For scripting against an entire module rather than one object at a time, this is the usual starting point, combined with ?findModule= if you only know the module's name.

Downloading a MIB in bulk formats

GET api/download.php?mib=<id>&format=raw|raw-deps|json|yaml|csv

Covered on the download button itself, but it's a usable API endpoint on its own. format=json and format=csv are useful for pulling a MIB's data into something else without reimplementing ?mib= yourself.

A Python script: looking up OIDs

A small, reusable function for querying the API from a script, built around ?node=, with a fallback to ?search= when you're not sure of the exact OID:

#!/usr/bin/env python3
"""
Minimal MIB Viewer API client - resolves an OID or object name to its
full detail. Requires: pip install requests
"""
import sys
import requests

BASE_URL = "https://mib-viewer.com/api/tree.php"


def lookup_oid(oid):
    """Fetch full detail for a known OID. Returns None if not found."""
    resp = requests.get(BASE_URL, params={"node": oid}, timeout=10)
    if resp.status_code == 404:
        return None
    resp.raise_for_status()
    return resp.json()["node"]


def search_by_name(term, scope="objects"):
    """Search by object name (or MIB name with scope='mibs')."""
    resp = requests.get(BASE_URL, params={"search": term, "scope": scope}, timeout=10)
    resp.raise_for_status()
    return resp.json()["results"]


def main():
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} ")
        sys.exit(1)

    query = sys.argv[1]
    is_numeric = all(part.isdigit() for part in query.split("."))

    if is_numeric:
        node = lookup_oid(query)
        if node is None:
            print(f"No object found at {query}")
            sys.exit(1)
        print(f"{node['name']} ({node['oid']})")
        print(f"  Kind:        {node['kind']}")
        print(f"  Syntax:      {node['syntax']}")
        print(f"  Access:      {node['access']}")
        print(f"  Description: {(node['description'] or '')[:200]}")
    else:
        results = search_by_name(query)
        if not results:
            print(f"No matches for '{query}'")
            sys.exit(1)
        for r in results[:10]:
            print(f"{r.get('name', '?')}  {r.get('oid', '')}")


if __name__ == "__main__":
    main()

Run as python3 lookup.py 1.3.6.1.2.1.1.1.0 for a direct OID, or python3 lookup.py sysDescr to search by name.

Using it from a traphandle script

The Using net-snmp guide covers a traphandle script that logs incoming traps. That version prints raw varbind lines as-is - if MIBS=+ALL isn't loaded locally, or the trap is from a vendor whose MIB isn't installed, those lines are unresolved numeric OIDs. A traphandle script can call the API instead of needing a local MIB file:

#!/usr/bin/env python3
"""
snmptrapd traphandle script - resolves each varbind's OID against the
MIB Viewer API before logging, so traps from vendors whose MIBs aren't
installed locally still log with readable names instead of bare OIDs.
Wire this up with: traphandle default /usr/local/bin/traphandler.py
Requires: pip install requests
"""
import sys
import re
import datetime
import requests

API_URL = "https://mib-viewer.com/api/tree.php"
LOG_FILE = "/var/log/snmp-traps.log"

OID_RE = re.compile(r"^(\.?\d+(?:\.\d+)+)\s+(.*)$")


def resolve_oid(oid):
    """Best-effort name lookup - falls back to the bare OID on any
    failure (network issue, not found, API down) rather than losing
    the trap data entirely."""
    try:
        resp = requests.get(API_URL, params={"node": oid.lstrip(".")}, timeout=3)
        if resp.status_code == 200:
            return resp.json()["node"]["name"]
    except requests.RequestException:
        pass
    return None


def main():
    lines = sys.stdin.read().splitlines()
    if len(lines) < 2:
        return

    hostname, source = lines[0], lines[1]
    timestamp = datetime.datetime.now().isoformat()

    with open(LOG_FILE, "a") as f:
        f.write(f"[{timestamp}] Trap from {hostname} ({source})\n")
        for line in lines[2:]:
            m = OID_RE.match(line.strip())
            if m:
                oid, rest = m.groups()
                name = resolve_oid(oid)
                label = f"{name} ({oid})" if name else oid
                f.write(f"    {label} {rest}\n")
            else:
                f.write(f"    {line}\n")


if __name__ == "__main__":
    main()

Each varbind's OID gets a lookup before being logged, with a fallback to the raw OID if the API call fails - a trap you can't fully decode is still more useful logged than dropped.