Skip to main content

macadress

Official Python client for the macadress.com MAC address and OUI vendor lookup API.

  • Vendor name, OUI, IEEE block, country, address type, EUI-64 / IPv6 link-local, randomization confidence, device guess
  • Keyless vendor-name lookup, plus keyed single / batch / directory-search calls
  • Typed dataclass results with a raw escape hatch, typed exceptions per failure mode
  • Sync Client and async AsyncClient from the same API, one dependency (httpx)
from macadress import Client

mac = Client("mk_live_xxx")

mac.vendor("00:03:93:AB:12:34")            # "Apple, Inc."   (no API key required)
mac.lookup("00:03:93:AB:12:34").country    # "US"

Install

pip install macadress

Requires Python 3.10+.

Getting a key

vendor() needs no key. Everything else does. A free key (1,000 lookups a day) is instant at macadress.com/signup; see pricing for more.

Usage

Create a client

from macadress import Client

mac = Client("mk_live_xxx")

# keyless: only vendor() will work
anon = Client()

# options
mac = Client(
    "mk_live_xxx",
    base_url="https://api.macadress.com",   # change only for a self-hosted deployment
    timeout=10.0,
    headers={"X-Trace": "my-app"},
)

# reuse / close
with Client("mk_live_xxx") as mac:
    ...

vendor() - name only, no key

Returns None when the address is valid but has no vendor to report (unregistered, private, or locally administered / randomized).

mac.vendor("00:03:93:AB:12:34")   # "Apple, Inc."
mac.vendor("02:1a:2b:3c:4d:5e")   # None

:, -, . and space grouping are all accepted, as is a bare 12-hex string.

lookup() - full analysis

r = mac.lookup("3C:22:FB:12:34:56")

r.organization              # str | None
r.vendor_lookup_reliable    # bool  (False for a private block / LAA)
r.oui                       # "3C:22:FB"
r.matched_prefix            # full matched block at its real width
r.block_type                # BlockType.MA_L (compares equal to "MA-L")
r.country                   # "US" | None
r.administration_type       # AdministrationType.UNIVERSALLY_ADMINISTERED | ...
r.potentially_randomized    # bool
r.randomization_confidence  # RandomizationConfidence.NONE | POSSIBLE | LIKELY
r.eui64                     # "3E:22:FB:FF:FE:12:34:56" | None
r.ipv6_link_local           # "fe80::3e22:fbff:fe12:3456" | None
r.device.category           # DeviceCategory.UNKNOWN (usually)
r.explanation               # plain-English summary
r.meta.database_version     # "2026-08-30"

Any field not covered by an attribute is still reachable:

r.get("vendor_location.city")   # dotted path into r.raw, default None
r.raw                           # the decoded payload as given

batch() - up to 100 at once

Results come back in input order; check each item.

for item in mac.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)

Raises ValueError (no request made) if the iterable is empty or has more than macadress.MAX_BATCH_SIZE (100) entries.

search_vendors() - the directory

result = mac.search_vendors("Cisco", country="US", limit=20)

result.total   # total matches, ignoring the limit
for block in result:
    print(block.block_type, block.organization, block.country)

health()

mac.health()   # bool, keyless, uncounted; a transport failure is False

Async

AsyncClient mirrors Client method for method:

import asyncio
from macadress import AsyncClient

async def main():
    async with AsyncClient("mk_live_xxx") as mac:
        print(await mac.vendor("00:03:93:AB:12:34"))
        r = await mac.lookup("3C:22:FB:12:34:56")
        print(r.organization)

asyncio.run(main())

Errors

Every failure is a MacadressError.

Class When
InvalidMACError HTTP 400, the input did not parse
AuthenticationError HTTP 401, missing or invalid API key
RateLimitError HTTP 429, per-minute rate exceeded. .retry_after (seconds) when sent
QuotaExceededError HTTP 429, billing-cycle quota spent. Subclass of RateLimitError
APIError any other 4xx/5xx, or an unreadable response
TransportError never reached the API: DNS, connection, TLS, timeout (__cause__ is the httpx error)
ConfigurationError bad client options (raised before any request)

Each carries .status_code, .request_id and .body where available.

from macadress import Client, RateLimitError, MacadressError

try:
    r = mac.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)

Development

python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"

pytest
mypy
ruff check .

The version lives in src/macadress/_version.py; keep CHANGELOG.md and the release tag in step with it.

Links

License

MIT, see LICENSE. A product of ApisOS FZE.

Metadata

Release files for macadress 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for macadress 1.0.0
File Size Uploaded Provenance
macadress-1.0.0.tar.gz 16.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for macadress 1.0.0
File Interpreter ABI Platform
macadress-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 31.1 kB

Release files / macadress-1.0.0.tar.gz

Download URL macadress-1.0.0.tar.gz
Size 16.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7062b10e5d012f45e49ee6e9d5e371ca5d68216273c7923859cde886c6300620
BLAKE2b-256 checksum
How to use checksums
364b3685f43438d7b96818c442dcc6ae7d74dc44a6dd97ae4ac25c01fd45674f
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 2, 2026.

Transparency log

Release files / macadress-1.0.0-py3-none-any.whl

Download URL macadress-1.0.0-py3-none-any.whl
Size 14.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
792a3916f1122f0a732675a802f4f7d1a6b2ec9931ad65aeda814cdce15b8904
BLAKE2b-256 checksum
How to use checksums
d1d03ac08e2a0022981b0f5b8fbf0b6d0cc028df165a0015d3566c00196bd0b6
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 2, 2026.

Transparency log

Security for macadress 1.0.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for macadress-1.0.0.tar.gz

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 2, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page