Skip to content
LogoLogo

@portable/rdap

Functions

Rdap.asn

Looks up an autonomous system number, such as 15169. The regional internet registry comes from IANA's bootstrap file.

Rejects with InvalidInputError for a number outside 0 to 4294967295, UnsupportedError for a number no registry serves, and NotFoundError when the registry has no record.

async function asn(
  number: number,
  options: asn.Options = {},
): Promise<Autnum>;
OptionTypeDefaultDescription
fetchFetchglobalThis.fetchThe function that sends each Request. Pass one to add headers, set a timeout, route through a proxy, or mock responses. Bootstrap files are cached separately for each fetch function.
signalAbortSignalCancels the lookup. It rejects with signal.reason, as fetch does.
nowanyThe current time, as a Date or a Temporal.Instant. lookup compares it with the time the bootstrap files were cached to decide whether they have expired.
import * as Rdap from '@portable/rdap';
 
const autnum = await Rdap.asn(15169);
autnum.name; // 'GOOGLE'

Rdap.domain

Looks up a domain name. The registry comes from IANA's bootstrap file (RFC 9224), which is cached in memory for 24 hours. Unicode names are converted to A-labels with the IDNA rules URL uses. When the registry links to the registrar's response, as gTLD registries do, that response is fetched too and its contacts are used.

Rejects with InvalidInputError for a malformed name, UnsupportedError when the TLD has no RDAP server, and NotFoundError when the name isn't registered.

async function domain(
  name: string,
  options: domain.Options = {},
): Promise<Domain>;
OptionTypeDefaultDescription
fetchFetchglobalThis.fetchThe function that sends each Request. Pass one to add headers, set a timeout, route through a proxy, or mock responses. Bootstrap files are cached separately for each fetch function.
signalAbortSignalCancels the lookup. It rejects with signal.reason, as fetch does.
nowanyThe current time, as a Date or a Temporal.Instant. lookup compares it with the time the bootstrap files were cached to decide whether they have expired.
followbooleantrueFetches the registrar's response when the registry links to it, and takes the contacts from it. A failed referral doesn't fail the lookup: referral.error holds the error.
import * as Rdap from '@portable/rdap';
 
const domain = await Rdap.domain('example.com');
domain.events.expiration; // Date
domain.entities.find((entity) => entity.roles.includes('registrar'))
  ?.name;

Rdap.ip

Looks up the network that contains an IPv4 or IPv6 address, or a prefix such as 192.0.2.0/24. The regional internet registry comes from IANA's bootstrap file, by the longest matching prefix.

Rejects with InvalidInputError for a malformed address, UnsupportedError for an address no registry serves, such as 10.0.0.1, and NotFoundError when the registry has no record.

async function ip(
  address: string,
  options: ip.Options = {},
): Promise<Network>;
OptionTypeDefaultDescription
fetchFetchglobalThis.fetchThe function that sends each Request. Pass one to add headers, set a timeout, route through a proxy, or mock responses. Bootstrap files are cached separately for each fetch function.
signalAbortSignalCancels the lookup. It rejects with signal.reason, as fetch does.
nowanyThe current time, as a Date or a Temporal.Instant. lookup compares it with the time the bootstrap files were cached to decide whether they have expired.
import * as Rdap from '@portable/rdap';
 
const network = await Rdap.ip('8.8.8.8');
network.cidrs; // ['8.8.8.0/24']
network.entities.find((entity) => entity.roles.includes('abuse'))
  ?.email;

Errors

Rdap.InvalidInputError

Thrown when the domain name, IP address or AS number can't be looked up as given, such as example..com, 999.1.1.1 or -1. No request is sent.

class InvalidInputError extends Errors.InvalidInputError {
  readonly kind: string;
}
import * as Rdap from '@portable/rdap';
 
await Rdap.ip('not an address').catch(
  (error) => error instanceof Rdap.InvalidInputError,
); // true

Rdap.NotFoundError

Thrown when the RDAP server answers 404 Not Found: the domain isn't registered, or no network or AS number record covers the query. response holds the 404 response, with its body cancelled.

class NotFoundError extends Errors.ResponseError {
  constructor(
    options: Errors.ResponseError.Options & {
      url: string;
    },
  );
  readonly kind: string;
  readonly url: string;
}
import * as Rdap from '@portable/rdap';
 
async function isRegistered(name: string) {
  try {
    await Rdap.domain(name, { follow: false });
    return true;
  } catch (error) {
    if (error instanceof Rdap.NotFoundError) {
      return false;
    }
    throw error;
  }
}

Rdap.ResponseError

Thrown when an RDAP server or IANA answers with an HTTP error other than 404, or with a body that isn't a JSON object. When fetch rejects, the lookup rejects with the same error.

class ResponseError extends Errors.ResponseError {
  constructor(
    options: Errors.ResponseError.Options & {
      url: string;
    },
  );
  readonly kind: string;
  readonly url: string;
  readonly body: unknown;
}
import * as Rdap from '@portable/rdap';
 
try {
  await Rdap.domain('example.com');
} catch (error) {
  if (error instanceof Rdap.ResponseError && error.status === 429) {
    console.log('rate limited');
  }
}

Rdap.UnsupportedError

Thrown when IANA's bootstrap files list no RDAP server for the query, as for .de domains, the private range 10.0.0.0/8, or a reserved AS number. The input is valid, and only the bootstrap file was fetched.

class UnsupportedError extends Errors.UnsupportedError {
  readonly kind: string;
}
import * as Rdap from '@portable/rdap';
 
await Rdap.ip('10.0.0.1').catch(
  (error) => error instanceof Rdap.UnsupportedError,
); // true

Types

Rdap.Autnum

An autonomous system number range, as Rdap.asn returns it.

type Autnum = Common & {
  name: string | undefined;
  start: number | undefined;
  end: number | undefined;
  type: string | undefined;
  country: string | undefined;
};

Rdap.Domain

A domain, as Rdap.domain returns it.

type Domain = Common & {
  name: string;
  unicodeName: string | undefined;
  nameservers: readonly string[];
  referral: Referral | undefined;
};

Rdap.Entity

A contact, with its jCard (RFC 7095) reduced to the first value of each common property. The raw jCard is in raw of the result, under entities[].vcardArray.

type Entity = {
  handle: string | undefined;
  roles: readonly string[];
  name: string | undefined;
  org: string | undefined;
  email: string | undefined;
  phone: string | undefined;
  address: string | undefined;
};

Rdap.Events

The events most callers need. Each one is undefined when the response doesn't have it or its date is unreadable.

type Events = {
  registration: Date | undefined;
  expiration: Date | undefined;
  lastChanged: Date | undefined;
};

Rdap.Network

An IP network, as Rdap.ip returns it.

type Network = Common & {
    name: string | undefined;
    version:  |  | undefined;
    startAddress: string | undefined;
    endAddress: string | undefined;
    cidrs: readonly string[];
    type: string | undefined;
    country: string | undefined;
    parentHandle: string | undefined;
};

Rdap.Referral

The registrar's response that a registry pointed to with a related link.

type Referral =
  | {
      url: string;
      raw: Record<string, unknown>;
      error?: undefined;
    }
  | {
      url: string;
      raw?: undefined;
      error: unknown;
    };