Skip to content

Svelte Tel Input – Phone Number Component for Svelte 5

Parse phone numbers easily.

A headless Svelte 5 toolkit for phone input.
Type nationally or internationally — always stored as E.164. You build the UI.

E.164 Storage Auto-detect Country Smart Formatting Validation SSR / SSG Svelte 5 Runes
Live Demo

Phone input that just works

Type any international number — auto-detected, formatted, and stored as E.164.

Try:
Live output
value
+14155552671
country
valid ✓ valid
Install

Up and running in seconds

pnpm add svelte-tel-input
Features

All the ingredients. You build the UI.

svelte-tel-input is headless — it handles parsing, formatting, country detection, and validation, but ships zero styles. Use any CSS framework, design system, or custom markup.

E.164 Storage

Phone numbers are always stored in E.164 format — the standard your backend and APIs expect.

Auto-detect Country

Paste any international number and the country is auto-detected from the dial code.

Smart Formatting

Numbers format as you type — national or international — cursor position preserved.

Built-in Validation

Catch invalid, too-short, and impossible numbers using libphonenumber-js under the hood.

SSR / SSG Ready

Works in SvelteKit (SSR) and Astro (SSG) with no window guards or client-only workarounds.

Svelte 5 Runes

Built with $state, $derived, and $bindable — fully reactive with zero ceremony.

Headless & Unstyled

No UI opinions — pair it with any CSS framework, design system, or component library. You own the markup.

Quick start

Three bindings. That's it.

Minimal setup — bind value, country, and valid and you're done.

Svelte 5
<script lang="ts">
  import { TelInput } from 'svelte-tel-input';
  import type { CountryCode } from 'svelte-tel-input/types';

  let value = $state('');
  let country = $state<CountryCode | null>('US');
  let valid = $state(true);
</script>

<TelInput
  bind:value
  bind:country
  bind:valid
  options={{ autoPlaceholder: true, spaces: true }}
/>