Pagination
Long lists come in pages. Pass next_cursor back as cursor until it is null.
ip_domains, domain_history and
lookup_asn (its ranges) return their lists in pages.
| Parameter | Meaning |
|---|---|
limit | Items per page, 1 to 1000; 100 when left out. On the Free plan a page holds at most 100: a larger limit is lowered, and next_cursor carries on. |
cursor | The previous page's next_cursor, unchanged. Leave it out for the first page. |
Each page has next_cursor, which is null on the last page. Each page counts one request.
import os
import requests
API = "https://api.ipalmanac.com"
HEADERS = {"Authorization": f"Bearer {os.environ['IPALMANAC_API_KEY']}"}
def domains_on(ip: str) -> list[dict]:
"""Every domain interval seen on the IP, ended ones included."""
items, cursor = [], None
while True:
params = {"include_ended": "true", "limit": 1000}
if cursor:
params["cursor"] = cursor
response = requests.get(f"{API}/v1/ip/{ip}/domains", headers=HEADERS, params=params, timeout=30)
response.raise_for_status()
page = response.json()
items += page["items"]
cursor = page["next_cursor"]
if cursor is None:
return itemsWhen a cursor stops working
A cursor belongs to the query it came from and to the data snapshot that answered it.
- Sent with a different query, it gets
400invalid_cursor. - Once the data is updated, it gets
410cursor_expired: start again without a cursor. Each page'srelease.idnames its snapshot, so pages with the samerelease.idbelong together.
Not paged
domain_hosting returns everything in one response. For a domain with more than 5,000 answer
intervals it covers the most recent ones and sets truncated: true.