Developer Guide

E.164 formatting and URL encoding for phone APIs

E.164 is the international standard phone number format: a leading plus sign, the country code, and the subscriber number, with no spaces, dashes or brackets, and a maximum of fifteen digits after the plus. The single gotcha that catches almost every new integration is that the leading + must be URL-encoded as %2B when it appears in a query string, since a raw + is interpreted as a space by URL parsers.

What E.164 actually requires

+447700900000 is valid E.164. 07700 900000, +44 (0) 7700 900000 and 0044-7700-900000 are not, and will fail validation or produce an incorrect lookup if sent as-is.

The URL encoding problem

A phone number in E.164 format is only half the job. When that number is passed as a query string parameter, as in GET /api/lookup?phone=+447700900000, the + character has a special meaning in a URL-encoded query string: it represents a space, left over from the application/x-www-form-urlencoded convention that most URL parsers still honour. Left unencoded, the number is silently corrupted before it reaches the API.

Correct
https://telebase.fatcatremote.com/api/lookup?phone=%2B447700900000
Incorrect (+ silently becomes a space)
https://telebase.fatcatremote.com/api/lookup?phone=+447700900000

The fix is always the same: percent-encode the + as %2B. Every mainstream language has a standard-library function that does this correctly for the whole string, so there is rarely a reason to hand-build the encoded string yourself.

Correct encoding in common languages

Python
from urllib.parse import quote
quote("+447700900000", safe="")
# '%2B447700900000'
JavaScript
encodeURIComponent("+447700900000")
// '%2B447700900000'
Shell (curl)
curl -s 'https://telebase.fatcatremote.com/api/lookup?phone=%2B447700900000' \
  -H 'Authorization: Bearer tb_live_xxxxxxxxxxxxxxxxxxxxxxxx'

In each case, encode the whole phone number string with the language's standard encoding function rather than manually replacing only the +; other characters in a malformed input could need encoding too, and the standard function handles all of them consistently.

Symptoms of getting this wrong

A raw, unencoded + typically produces a 400 response, since the API receives a number with a space where the + should be and it fails E.164 validation. If you are seeing unexpected 400 responses for numbers that look correctly formatted in your own logs, check the raw request URL your HTTP client actually sent, not just the string you passed to it, since some HTTP libraries handle query encoding automatically and some do not.

Quick checklist

SIM swap detection is launching. Early access is open now.

Every correctly encoded E.164 lookup returns the simSwap field today, currently UNKNOWN in GB, DE, NL and FR while carrier registration completes. See the SIM swap detection API.

New to the API? Start with the quickstart guide for the first request end to end.

$0.03 per query. No contract. No minimum spend. Billed via Paddle.
Request early access