Python library
macadress.com for Python.
A typed Python client for the MAC address and OUI vendor lookup API: vendor name, IEEE block, country, address type, EUI-64 / IPv6 derivation, randomization confidence and a device guess. Sync and async, one dependency.
httpx). Ships type information (py.typed). Source at github.com/sapisos/macadress-python.
Install
pip install macadress
Look up a vendor
The name-only lookup needs no API key:
from macadress import Client
client = Client() # keyless
client.vendor("00:03:93:AB:12:34") # "Apple, Inc."
client.vendor("02:1a:2b:3c:4d:5e") # None (unregistered, private, or randomized)
Full analysis
Everything else needs a free API key. Results are typed dataclasses:
client = Client("mk_live_xxx")
r = client.lookup("3C:22:FB:12:34:56")
r.organization # str | None
r.country # "US" | None
r.block_type # BlockType.MA_L (compares equal to "MA-L")
r.potentially_randomized # bool
r.randomization_confidence # RandomizationConfidence.NONE | POSSIBLE | LIKELY
r.eui64 # "3E:22:FB:FF:FE:12:34:56" | None
r.device.category # DeviceCategory.UNKNOWN (usually)
r.explanation # plain-English summary
# anything without a typed attribute is still reachable
r.get("vendor_location.city")
r.raw
Batch and directory search
for item in client.batch(["00:03:93:00:00:00", "3C:22:FB:00:00:00", "bad"]):
if item.failed:
print(item.input, "->", item.error)
else:
print(item.input, "->", item.organization)
result = client.search_vendors("Cisco", country="US", limit=20)
for block in result:
print(block.organization, block.country)
batch() raises ValueError without making a request if the iterable is empty or has more than macadress.MAX_BATCH_SIZE (100) entries.
Async
AsyncClient mirrors Client method for method:
import asyncio
from macadress import AsyncClient
async def main():
async with AsyncClient("mk_live_xxx") as client:
print(await client.vendor("00:03:93:AB:12:34"))
r = await client.lookup("3C:22:FB:12:34:56")
print(r.organization)
asyncio.run(main())
Errors
Every failure is a MacadressError: InvalidMACError (400), AuthenticationError (401), RateLimitError (429, with .retry_after), QuotaExceededError, TransportError for a network failure, ConfigurationError for bad options. Each carries .status_code, .request_id and .body.
from macadress import Client, RateLimitError, MacadressError
try:
r = client.lookup(value)
except RateLimitError as exc:
time.sleep(exc.retry_after or 5)
except MacadressError as exc:
log.warning("macadress %s: %s (%s)", exc.status_code, exc, exc.request_id)
Quota
Each lookup(), batch() address, and search_vendors() call is one API call against your plan, the same as a direct REST call: see pricing. The keyless vendor() endpoint is free for 1,000 lookups a day per IP; passing a key lifts that to your plan quota.
Links
- Package: pypi.org/project/macadress
- Source and issues: github.com/sapisos/macadress-python
- API reference: macadress.com/docs