spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1# peeringdb — PeeringDB public API23| | |4|---|---|5| id / implementation | `peeringdb` (`apps/worker/src/connectors/datasets/peeringdb.ts`) |6| kind / mode / priority | dataset / api / 2 |7| API | https://www.peeringdb.com/api/ (`fac`, `campus`, `org`, `ix`, `ixfac`, `netfac`, `net`, `carrier`, `carrierfac`), always `?depth=0` |8| entities | `NormalizedFacility` (`peeringdb:fac:<id>`), `NormalizedIxp` (`peeringdb:ix:<id>`), `NormalizedCampus` (`peeringdb:campus:<id>`), `NormalizedOperator` (`peeringdb:org:<id>` facility owners; `peeringdb:net:<id>` NSP networks and `peeringdb:carrier:<id>` carrier objects, kind `carrier`) |9| schedule | `facilities: daily`, `ixps: daily` (incremental `since=`), `campuses/operators/carriers: weekly`; full refresh every `params.fullRefreshDays` (7) |10| requests per run | 5 primary + 9 lookup/join tables, each URL once per run (memoized), ≥ 2 s apart → ~14 requests, ≈ 25 MB |11| attribution | **"Data: PeeringDB"** |1213## License / terms (verified 2026-09-11) — READ THIS1415PeeringDB publishes no open-data license (no CC/ODbL). https://docs.peeringdb.com/ links only to the Acceptable Use Policy, https://www.peeringdb.com/aup, which states (verbatim):1617> "Except for Internet operational purposes approved by PeeringDB, no part of the PeeringDB data may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, recording, or otherwise, without prior permission of PeeringDB on behalf of the copyright holders. Any use of this material to target advertising or similar activities is explicitly forbidden and will be prosecuted. […] The PeeringDB data may not be passed on in bulk to any other person or organization unless approved by PeeringDB. Any request to pass on information to any other person or organization will be evaluated on the statement of purpose outlined by the requestor. Users will not be able to download the full contents of the database unless the intended use is for "Internet operational issues". These words are tightly defined and would include network trouble-shooting, abuse reporting, and Internet research and analysis. It would not include compiling marketing lists, demographic mapping, or any other commercial application."18>19> "© 2004-2026 PeeringDB All Rights Reserved. By using this service, you agree to adhere to our AUP."2021Reading: DataCenterIndex's use (a structured index of facilities/IXPs for research and analysis, attributed) fits "Internet research and analysis", but the AUP requires PeeringDB's *approval* for bulk reproduction and forbids "commercial application". **Action for the owner before publishing PeeringDB-derived records: e-mail support@peeringdb.com with a statement of purpose and request approval (and an API key, see below).** Until then the connector is functional but should be considered "verification/reconciliation input", and the UI must show "Data: PeeringDB" wherever a PeeringDB-sourced fact is displayed. The YAML `license` field carries the AUP quote so `sources.license` is accurate.2223## Query limits (https://docs.peeringdb.com/howto/work_within_peeringdbs_query_limits/, retrieved 2026-09-11)2425> "Duplicate queries: Repeated anonymous identical requests with a response size above 100kb are being limited to 1/hour. Repeated anonymous identical requests of any size are being limited to 2/minute. Query rate limit: Anonymous queries limited to 20/minute per IP address. Authenticated queries limited to 40/minute per user or organization […] Please use API Keys when automating queries to PeeringDB and set a User-Agent header that identifies the unique software you are using […] We also encourage you to leave at least two seconds between queries."2627Consequences implemented:28- every upstream URL is fetched **once per run** (`fetchJsonOnce`, memo keyed by runId) and requests are spaced by `params.minDelayMs` (2 000 ms), `fetch.rpm: 20`, `concurrency: 1`;29- `PEERINGDB_API_KEY` (env) → header `Authorization: Api-Key …` for the authenticated tier (recommended; also lets PeeringDB contact us);30- HTTP 429 is logged with `Retry-After`; a facility document whose join tables are unavailable is **aborted** (no partial carrier/IX lists) and retried at the next run;31- during verification an identical anonymous `fac?depth=0` request repeated within the hour was throttled ("Expected available in 36 minutes"). Never run two full loads within an hour without an API key.3233`robots.txt` only disallows `/register`, `/account/login`, `/username-retrieve`, `/reset-password` → `/api/` is allowed (`respectRobots: true`).3435## Documents and mapping3637**facilities** (`fac?depth=0[&since=]`) — composed with `campus`, `ixfac(fields)`, `ix(fields)`, `netfac(fields)`, `net?info_type=NSP(fields)`, `carrier`, `carrierfac(fields)`:3839| field | source |40|---|---|41| `name`, `aliases` | `name`; `aka`, `name_long` (distinct, non-empty) |42| `operatorName` / `operatorKey` | `org_name` / `peeringdb:org:<org_id>` |43| `campusName` / `campusKey` | `campus.name` / `peeringdb:campus:<campus_id>` |44| `address`, `city`, `regionName`, `countryIso2`, `postalCode` | `address1, address2`; `city`; `state`; `country` (ISO-2); `zipcode` |45| `geo` | `latitude`/`longitude` → precision **`exact`**, source `dataset:peeringdb`; null when absent (never geocoded here) |46| `status` | `ok` → `operational`; `pending`/`deleted` records are skipped (deletions are **not** propagated as closures — a PeeringDB deletion is often a merge/duplicate) |47| `facilityType` | `carrier_hotel` when `ix_count ≥ 3` and `net_count ≥ 150` (`params.carrierHotelMinIx/MinNets`), else `colocation` |48| `carriers` | names of PeeringDB `carrier` objects present (`carrierfac`) ∪ networks present (`netfac`) whose `info_type`/`info_types` contains `NSP` |49| `ixps` | IX names present (`ixfac`) |50| `website`, `description` | `website` (http(s) only), `notes` |51| `externalIds` | `peeringdb_fac`, `peeringdb_org`, `peeringdb_campus`, `clli` |52| `facts` | `networkCount` (`net_count`), `ixCount` (`ix_count`), `carrierCount` (`carrier_count`), `property` (Owner/Lessee), `diverseServingSubstations`, `availableVoltageServices` — per-field provenance `dataset-field:<name>` |5354Not used: `created` (registration date, not an opening date), `region_continent`, `npanxx`, contact fields (personal data).5556**ixps** (`ix?depth=0`) — `name`, `nameLong`, `city`, `countryIso2`, `regionContinent`, `website`, `networkCount = net_count`, `facilityKeys` from `ixfac` (`peeringdb:fac:<fac_id>`), `externalIds { peeringdb_ix, peeringdb_org }`.57**campuses** (`campus?depth=0`) — `name`, `operatorName = org_name`, `city`, `countryIso2`, `externalIds { peeringdb_campus, peeringdb_org }` (PeeringDB campuses carry no coordinates → `geo: null`).58**operators** (`org?depth=0&fields=…`) — only organisations owning ≥ 1 `ok` facility (join on `fac?fields=id,org_id,status`): `name`, `aliases`, `website`, `hqCountryIso2`, `hqCity`, `kind: null` (not guessed), `externalIds { peeringdb_org }`.59**carriers** (`net?depth=0&info_type=NSP&fields=…` + `carrier`) — `kind: "carrier"`, `externalIds { peeringdb_net, asn, peeringdb_org }` for NSP networks; `{ peeringdb_carrier, peeringdb_org }` for carrier objects.6061Incremental mode: state `peeringdb:lastRunAt` / `peeringdb:lastFullAt`; after a full load, subsequent runs add `since=<lastRunAt − 1 h>` (unix seconds) to the five primary URLs (PeeringDB returns objects updated since, including `status: deleted`). Join/lookup tables are always fetched in full (presence lists are recomputed from scratch). State is written in `discover()` (not in dry runs); a run that dies midway loses at most one incremental window, recovered by the weekly full load.6263## Verified live (2026-09-11)6465```66node node_modules/tsx/dist/cli.mjs scripts/try-connector.ts config/connectors/peeringdb.yaml --limit 5 --json /tmp/peeringdb.json (anonymous, no API key)67fac?depth=0 200 1.1 s → 5 860 records → 5 860 facilities, 5 860 valid, 0 rejected68ix?depth=0 429 retry-after 1255 s (identical anonymous request > 100 kB repeated within the hour: the probe 38 min earlier) → 0 entities69campus?depth=0 200 → 76 campuses, 76 valid70org?depth=0&fields=… 200 1.3 s → 2 605 facility-owning organisations, 2 605 valid71net?depth=0&info_type=NSP&fields=… 200 0.6 s → 4 193 NSP networks + 286 carrier objects = 4 479 carrier operators, all valid72TOTAL 13 020 entities, 13 020 valid, 0 rejected, 0 warnings, 11 fetches, 26 s (2 s pacing)73```7475Facilities coverage: 5 255 / 5 860 with coordinates (`exact`), 5 860 with a country, 3 720 with ≥ 1 carrier/NSP present, 2 158 with ≥ 1 IX present, 206 attached to a campus; 57 typed `carrier_hotel` (ix_count ≥ 3 and net_count ≥ 150), 5 803 `colocation`.76Sample: `peeringdb:fac:1` "Equinix DC1-DC15,DC21-DC22 - Ashburn" — operator Equinix, Inc. (`peeringdb:org:2`), campus "Equinix Ashburn" (`peeringdb:campus:14`), 21715 Filigree Ct, Building F, Ashburn VA 20147-6205 US, geo 39.016363/−77.459023 exact, `carrier_hotel`, carriers list (123NET, AT&T US, Angola Cables…), facts networkCount 516 / ixCount 8 / carrierCount 14.7778IX document, re-verified once the hourly window reopened (03:48 EDT, `--url https://www.peeringdb.com/api/ix?depth=0`, group inferred from the path):7980```81ix?depth=0 200 0.3 s → 1 323 records → 1 323 IXPs, 1 323 valid, 0 rejected (2 fetches: ix + ixfac)82```83Coverage: 1 323 with a country, 1 318 with a website, 1 226 with `networkCount`, 960 with ≥ 1 `facilityKeys` (from 4 521 ixfac rows).84Sample: `peeringdb:ix:1` "Equinix Ashburn" (nameLong "Equinix Internet Exchange Ashburn", US, North America, 347 networks, facilityKeys `peeringdb:fac:1`, `peeringdb:fac:710`, `peeringdb:fac:15438`, externalIds peeringdb_ix 1 / peeringdb_org 2).8586## Quirks / gaps8788- Anonymous tier: the `fac?depth=0` dump (~6 MB) can be fetched once per hour per IP. Use an API key in production.89- `net` full dump is 40 MB → we only fetch NSP networks with a `fields=` projection (~0.9 MB); `netfac` with `fields=` is ~3.9 MB (vs 14 MB).90- Presence lists can be long (Equinix Ashburn: 516 networks, of which the NSP subset is kept) — `carriers` is a *set of names*, counts live in `facts`.91- PeeringDB `org` records for facility owners are 3 000+ organisations, many small ISPs registering their own site as a "facility"; treat `net_count = 0` facilities as low-signal in ranking.92- Deleted/merged facilities are not propagated (needs a "missing from full load" reconciliation pass in ingest to flag `closed`/merged — out of scope for the connector).93