ScreenshotNeo

BlogHow-to

How to Create a Click-to-Call Phone Link in HTML

Create accessible HTML phone links with tel:, international number formatting, device behavior, testing guidance, and troubleshooting.

By the ScreenshotNeo team1 October 20266 min read

The direct answer is an anchor whose href starts with tel::

<a href="tel:+1-212-555-0101">+1-212-555-0101</a>

When a visitor activates the link, the browser passes the telephone URI to the device or calling application. A phone may offer to call immediately; a desktop may open Skype, FaceTime, a softphone, or another configured handler. The HTML cannot guarantee that every device can place a call.

Use a real number in production and keep the number in the link text so the destination and action are clear:

<p>Call our support team: <a href="tel:+1-201-555-0111">+1 (201) 555-0111</a></p>

The visible text may use a local format, while the URI should use the global telephone-number form recommended by RFC 3966. For a North American number, that means a leading country code such as +1.

Global URI, local display

<a href="tel:+442071838750">020 7183 8750</a>

Do not put spaces, parentheses, or visual separators in the URI unless your target calling software specifically requires them. Keep formatting for the human-readable label.

Use the number or an explicit action as the label. “Click here” gives users and screen-reader users no useful context when links are listed out of order.

<ul>
  <li>
    Sales: <a href="tel:+1-800-555-0142">Call sales at +1 (800) 555-0142</a>
  </li>
  <li>
    Support: <a href="tel:+1-800-555-0188">Call support at +1 (800) 555-0188</a>
  </li>
</ul>

Keep the anchor keyboard-focusable. A normal <a> element already supports keyboard navigation and assistive technology. Do not replace it with a <div> and a click handler.

Optional visual styling

.phone-link {
  display: inline-block;
  color: #0b57d0;
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.phone-link:focus-visible {
  outline: 3px solid #ffbf47;
  outline-offset: 3px;
}
<a class="phone-link" href="tel:+1-212-555-0101">Call +1 (212) 555-0101</a>

3. Add a complete contact example

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Contact support</title>
  <style>
    body { font: 1rem/1.5 system-ui, sans-serif; margin: 2rem; }
    .phone-link { font-weight: 700; }
    .phone-link:focus-visible { outline: 3px solid #ffbf47; outline-offset: 3px; }
  </style>
</head>
<body>
  <main>
    <h1>Contact support</h1>
    <p>Phone support is available Monday through Friday.</p>
    <p>
      <a class="phone-link" href="tel:+1-800-555-0188">
        Call support at +1 (800) 555-0188
      </a>
    </p>
  </main>
</body>
</html>

A tel: URI identifies a telephone resource; it does not force a call. Mobile operating systems commonly open the Phone app or show a confirmation prompt. Desktop systems may show a chooser, open a softphone, save the number, or do nothing if no handler is installed. Browser and operating-system settings control the result.

MDN’s anchor documentation describes this variable behavior. RFC 3966 also requires a web client to obtain the user’s explicit consent before placing a call. Never attempt to initiate calls automatically from page load or hidden script.

Apple’s archived Phone Links guidance notes that an iOS device without the Phone app can display a warning. Treat that as platform guidance, not a promise for every current iOS release.

5. Common variants

<a class="button" href="tel:+1-415-555-0136">Call now</a>

Keep an accessible name that explains the action. If several numbers appear on one page, include the department or number in each label.

Use an extension

<a href="tel:+1-212-555-0101;ext=204">Call +1 (212) 555-0101, extension 204</a>

Extension handling varies by device and calling application. If automatic extension dialing is unreliable, show the extension separately so the caller can enter it after connection.

Use a country-specific number

<a href="tel:+61293744000">Call +61 2 9374 4000</a>

Store and generate numbers consistently in international form when your site serves multiple countries. Do not silently rewrite a visitor’s local number without knowing the country context.

6. Testing checklist

  1. Inspect the rendered anchor and confirm that href begins with tel:.
  2. Activate it on a phone with a normal Phone app and verify the confirmation screen shows the intended number.
  3. Test a desktop with the calling software your visitors use.
  4. Keyboard-tab to the link and activate it with Enter.
  5. Check the label at 200% zoom and with a screen reader’s link list.
  6. Verify that analytics or consent scripts do not intercept the click and change the URI.

7. Troubleshooting

Symptom Likely cause Fix
Nothing happens on desktop No application is registered for tel:. Install or configure a calling application, or provide the number as visible text for manual dialing.
The wrong number appears Formatting or a copied character changed the URI. Inspect the final HTML, remove punctuation from href, and keep the international country code.
The link is not keyboard reachable An anchor was replaced with a non-semantic element or has tabindex="-1". Use a native <a href="tel:..."> and remove the negative tabindex.
A script opens a call without asking Custom JavaScript is attempting an automatic call. Remove automatic activation. Require a user gesture and let the operating system request consent.
Clicks are tracked but calling fails An analytics handler calls preventDefault() or rewrites the link. Track the event without cancelling the default action; test the final URI after all scripts run.
Users see an iOS warning The device lacks the Phone app or uses a restricted configuration. Leave the number visible and explain that another calling app or manual dialing may be required.

8. Performance, reliability and privacy

A tel: link is local markup. It adds no network request, API dependency, or measurable page-load work. Reliability depends on the visitor’s device, operating system, permissions, and calling software.

Do not put sensitive information in the URI. Treat phone numbers as public page content, protect them from unwanted scraping where appropriate, and avoid embedding tracking identifiers in a tel: value unless your calling system explicitly supports them.

9. Screenshot the finished page automatically

After adding a phone link, you may need screenshots for documentation, visual regression checks, or QA across contact-page variants. ScreenshotNeo captures a URL through one GET request and returns PNG, JPEG, WebP, or PDF. It removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed. Each response reports its page verdict and billing status in headers.

Or skip the browser setup

Use the API documented at ScreenshotNeo’s developer docs:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/contact -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com/contact"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com/contact' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. It supports full-page and element captures, device presets, custom viewports, retina scale, waits, custom CSS and JavaScript, request blocking, headers, cookies, user agents, geolocation, caching, signed links, async jobs, bulk capture, and usage reporting. Every feature is included on every plan. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.

Create a free ScreenshotNeo account and start with 1,000 screenshots a month at no charge.

10. FAQ

Does tel: work on every browser?

Browsers can recognize the URI, but the result depends on the operating system and an installed calling handler. Always provide the number as readable text.

Should the visible number and URI match exactly?

They should identify the same number. The URI can use global formatting while the visible label uses a local format.

Can JavaScript place a call automatically?

No. A web client must obtain explicit user consent. Use a normal user-activated anchor.

Should I add target="_blank"?

No. A telephone URI is not a normal web page, so opening a new tab is unnecessary and can make handler behavior less predictable.

What if I need a web call instead of a phone call?

Use the calling provider’s documented web or application URL scheme. Keep tel: for telephone-number resources.

Sources