tel: and mailto: links: format and href/text mismatches
A phone link whose href differs from the number on screen dials the wrong person. squirrel validates both formats and compares them with the visible text.
What tel: and mailto: links are
tel: and mailto: are URI schemes that hand a phone number or an email address to the device’s own application. RFC 3966 defines the phone form: it requires the global form, a leading + and the full number, whenever the number can be represented that way, permits the visual separators -, ., ( and ), and requires a phone-context parameter for a local number. RFC 6068 defines the mail form, including the ?subject= and ?body= parameters.
The failure that matters is a mismatch. When the href and the visible text carry different numbers or addresses, tapping the link contacts someone other than the person shown on screen. That is usually an edit applied to one and not the other.
What squirrel checks
The rule runs on every crawled page over every a[href] starting with tel: or mailto:, and over Cloudflare’s email address obfuscation links (/cdn-cgi/l/email-protection, on any host), which a browser turns into mailto: addresses. Those count as mailto: links. The address is decoded from the link’s fragment or its data-cfemail attribute and checked like any other, and a link whose address cannot be decoded is counted and never reported as invalid or mismatched. Six check names are possible and at most five appear in one result, since the last only fires when neither link type is present:
tel-linkswarns when a phone value has no digit or+, or is shorter than seven characters. Message:<invalid>/<total> tel: link(s) may be invalid. It passes otherwise with<total> tel: link(s) found.mailto-linkswarns when an address is present but has no@or no dot. Message:<invalid>/<total> mailto: link(s) may be invalid. It passes otherwise with<total> mailto: link(s) found. Format validation is skipped only for an empty recipient followed by a?, themailto:?subject=…share pattern; a baremailto:with nothing after it still warns.tel-mismatchwarns when the link text contains three or more consecutive digits that do not match the href. Message:<count> tel link(s) have mismatched phone number in href vs display text, each item labelledhref "<href number>" ≠ text "<link text>"with a markup snippet.tel-trunk-prefixreports at info status when the link text writes the optional trunk prefix(0)after a calling code, as in+49 (0)6061 630 980 0, and the number without that 0 matches the href. Message:<count> tel link(s) show the optional trunk prefix (0) in an international number; drop it (ITU-T E.123), each item labelledtext "<link text>": use "<international form>"with a markup snippet. The link dials the number shown, so this is formatting advice rather than a mismatch, and such a link is never also reported undertel-mismatch. It does not count toward the score and is not listed as an issue in the report. Digit grouping does not matter here, so+33 (0)1 23 45 67 89qualifies although it has no three consecutive digits.mailto-mismatchwarns when the link text looks like an email address and differs from the href, compared case-insensitively. Message:<count> mailto link(s) have mismatched email in href vs display text.tel-mailtoreports info when the page has neither kind of link. Message:No tel: or mailto: links found.
Numbers match on an exact digit comparison, on either digit string ending with the other, or on a trunk-prefix comparison. That last one drops a single leading zero from either side and accepts the pair when the shared suffix is at least five digits and the other number carries exactly two or three extra leading digits, the length of a country calling code. It works in both directions and does not require a literal +, so +61414123456 and 0414 123 456 are not a mismatch. Severity for the rule is info, weight 2.
The (0) reading applies only to the link text, never to the href, and only to calling codes whose national trunk prefix is 0 and is dropped when dialling from abroad, according to the ITU-T list of dialling procedures: +31 (Netherlands), +32 (Belgium), +33 (France), +41 (Switzerland), +43 (Austria), +44 (United Kingdom), +49 (Germany), +61 (Australia), +64 (New Zealand) and +353 (Ireland). For every other calling code the text is read literally. Italy (+39), for example, has no trunk prefix: its numbers keep the leading 0 after the country code, so +39 (0)6 1234 567 against tel:+3961234567 is still a mismatch. A German display number that differs from the href in any other digit is a mismatch too.
How to fix it
<a href="tel:+61292223333">(02) 9222 3333</a>
<a href="mailto:sales@example.com">sales@example.com</a>Put the E.164 form in the href and the locally readable form in the text. Generate both from one stored value so an edit cannot change only one of them. In international notation leave the trunk prefix out of the text as well: +49 6061 630 980 0, not +49 (0)6061 630 980 0.
A share link with no recipient, mailto:?subject=Look%20at%20this, is valid and is deliberately not validated.
| Rule ID | links/tel-mailto |
| Category | Links |
| Scope | Per-page |
| Severity | info |
| Weight | 2/10 |
Enable / disable
Disable this rule
[rules]
disable = ["links/tel-mailto"]Disable all Links rules
[rules]
disable = ["links/*"]Enable only this rule
[rules]
enable = ["links/tel-mailto"]enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.
Related rules
- eeat/contact-page: whether the site publishes contact details at all.
- eeat/physical-address: the address that usually sits next to them.
- schema/local-business: the structured data carrying the same phone number.
- links/invalid-links: hrefs that do not parse at all.
Links findings ship in every audit next to the SEO, performance and agent experience rules. See Fix SEO issues with AI for how an agent works through a report.
References
- RFC 3966: The tel URI for telephone numbers
- RFC 6068: The mailto URI scheme
- ITU-T E.123: Notation for national and international telephone numbers
- ITU-T dialling procedures: international prefix, national (trunk) prefix and national (significant) number
Check your site
Run squirrel audit https://example.com and open the Links section of the report. Every mismatch is listed with the href, the visible text and a markup snippet. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.