Format an international phone number by country
Phone numbers are easy to store as arbitrary text and surprisingly hard to present consistently.
Run — free
This formatter takes a phone number together with a two-letter country code, removes ordinary display punctuation, verifies the country calling code when one is supplied, and checks the exact national digit count. It then returns a clean international display form and compact E.164 form. Invalid lengths and mismatched calling codes produce an explicit error instead of a plausible-looking but unreliable result.
Provide a number and the country it belongs to
Enter the phone number in the form you already have and select its two-letter country code. National input may contain familiar separators such as spaces, parentheses, periods, or hyphens. You may also submit an international number beginning with a plus sign, or use the common 00 international prefix. When an international prefix is present, the formatter checks that its calling code agrees with the selected country. That check matters because the same sequence of national digits can look structurally valid in more than one place. The country is therefore an explicit instruction, not a guess based on the digits. For countries that use a domestic trunk zero, national input may retain that zero; it is removed where international notation requires its omission. The result includes the normalized ISO country code, calling code, national significant number, compact E.164 value, and a spaced display value. This makes the response useful both for human-facing interfaces and for normalized storage or downstream comparisons.
Understand what the validation guarantees
This tool performs structural validation for the countries listed in the country selector. It verifies allowed characters, the relationship between an explicit calling code and the selected country, and the expected number of national digits. A mismatch returns an error that names the country, expected count, and received count. That behavior is intentionally strict: silently padding, truncating, or inventing digits would create a number that belongs to nobody. Structural validity does not prove that a line is assigned, active, reachable, mobile, or owned by a particular person. It also does not contact a carrier or send a verification message. The formatter operates entirely on the supplied text using a fixed country-rule table. Because there is no network lookup, the same input always gives the same response, and the number is not shared with a directory service. Treat the output as a reliable representation of a structurally conforming number, not as evidence that the subscriber exists or has consented to contact.
Use the two normalized forms appropriately
The formatted field is designed for display: it begins with the plus-prefixed country calling code and separates the national digits into familiar country-specific groups. The e164 field removes those spaces and is better suited to databases, equality checks, API payloads, and links that expect a compact international value. Store the country code alongside the normalized number when your application needs to preserve the user's declared context. If you accept phone numbers in a form, validate them before saving so a digit-count error can be corrected while the user still has the source at hand. For imports, keep the original cell in an audit column and place the normalized result in a separate field; this prevents a cleanup operation from erasing evidence about the input. Applications should also preserve leading zeros by treating every phone value as text, never as a numeric type. Finally, remember that formatting is not permission: apply your normal consent, privacy, and messaging rules before using any returned number for calls or messages.
What you can do with it
Normalize customer-entered numbers
Reject incorrect digit counts immediately and save one consistent international representation.
Clean a contact import
Convert mixed punctuation and national notation into stable display and E.164 fields.
Prepare numbers for another API
Produce a compact international value while retaining a readable grouped version for review.
FAQ
What does the API request cost?
Each request costs $0.002. The browser version can run locally on this page.
Does a valid result mean the number is active?
No. It confirms the supported country's structure and digit count, not assignment, reachability, ownership, or consent.
Can I include spaces or punctuation?
Yes. Spaces, parentheses, periods, and hyphens are ignored. A plus sign is allowed only at the beginning.
Can I submit an international number?
Yes. Use a leading plus sign or 00 prefix. Its calling code must match the selected country.
Why was the domestic leading zero removed?
Several countries use a trunk zero only for domestic dialing. International notation omits it, so the normalized value follows that convention.
Why is my country not listed?
The capability only exposes countries with an explicit tested rule. It returns an error instead of guessing for unsupported numbering plans.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/data/phone-number-format \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"phone_number":"(202) 555-0147","country_code":"US"}'const res = await fetch("https://api.kit.forhosting.com/data/phone-number-format", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"phone_number": "(202) 555-0147",
"country_code": "US"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/data/phone-number-format",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"phone_number": "(202) 555-0147",
"country_code": "US"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/data/phone-number-format", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"phone_number":"(202) 555-0147","country_code":"US"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"phone_number":"(202) 555-0147","country_code":"US"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/data/phone-number-format", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"phone_number": "(202) 555-0147",
"country_code": "US"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "data.phone_number_format",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |