Search by

ipfy / homoglyph

manojmurulinath

Detect visually confusable domain names using Unicode UTS #39.

Package info

github.com/ipfy/Homoglyph

Language:JavaScript

pkg:composer/ipfy/homoglyph

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-09-10 13:04 UTC

This package is auto-updated.

Last update: 2026-09-10 14:55:34 UTC


README

Unicode-aware detection of visually confusable domain names.

Homoglyph is a multi-language, standards-based library for spotting Unicode homoglyph / homograph structure in domain names, using Unicode UTS #39 17.0.0.

paypal.com
раypal.com

Those strings are not the same domain. The second mixes Cyrillic letters that UTS #39 maps as confusable with Latin.

It is for developers who accept domains through email fields, URL fields, registration forms, and similar inputs.

Implementations

One GitHub repository, ipfy/Homoglyph, ships native packages:

Language Package Install
JavaScript npm @ipfy/homoglyph npm install @ipfy/homoglyph
Python PyPI ipfy-homoglyph pip install ipfy-homoglyph
PHP Packagist ipfy/homoglyph composer require ipfy/homoglyph

All three implement the same Homoglyph specification (see docs/DESIGN.md and docs/ARCHITECTURE.md), the same Unicode 17.0.0 confusable data, and the shared corpus in conformance/cases/.

JavaScript additionally provides browser warn() / reject() helpers. Python and PHP provide the core detect() API only.

What it is — and is not

The security boundary is the domain. Email local-parts and URL paths, queries, and fragments are not treated as hostname evidence.

Observation Meaning
Unicode in a domain Not malicious. IDNs are legitimate.
Non-Latin Not malicious.
Punycode / xn-- Not malicious. Valid A-labels are decoded, then analyzed.
Mixed script Not automatically malicious.
detected: true A UTS #39-relevant issue worth reporting
rejectable: true High-confidence finding suitable for hard enforcement

Homoglyph does not decide whether a domain is a phishing site. It is not a blacklist, reputation service, DNS client, or TLD policy engine.

JavaScript (npm)

npm install @ipfy/homoglyph
import Homoglyph from '@ipfy/homoglyph';

const result = Homoglyph.detect('раypal.com');
if (result.detected) {
  console.log(result.reason, result.domain, result.rejectable);
}

CDN (IIFE, globalThis.Homoglyph):

<script src="https://cdn.jsdelivr.net/npm/@ipfy/homoglyph/dist/homoglyph.min.js"></script>

Browser-only helpers: Homoglyph.warn(input) and Homoglyph.reject(input). See below. There is no init().

Python (PyPI)

pip install ipfy-homoglyph
import homoglyph

result = homoglyph.detect("раypal.com")
if result.detected:
    print(result.reason, result.domain, result.rejectable)

PHP (Packagist)

Requires PHP 8.1+ and ext-intl (Unicode NFC/NFD via Normalizer).

composer require ipfy/homoglyph
use IPfy\Homoglyph\Homoglyph;

$result = Homoglyph::detect('раypal.com');
if ($result->detected) {
    echo $result->reason, ' ', $result->domain;
}

Email and URL behavior

user@раypal.com                 → analyze раypal.com
mаnοj@paypal.com               → domain paypal.com; not rejectable
https://раypal.com/login        → analyze раypal.com
https://example.com/раypal     → path ignored
https://example.com/?q=раypal  → query ignored
https://example.com/#раypal    → fragment ignored
пример.com                     → labels analyzed independently (not mixed-script)

Punycode / IDNA

Valid xn-- A-labels are decoded and then analyzed. Punycode itself is not evidence of malice. Successful Punycode decoding is not full IDNA validation.

Unicode

Item Value
Unicode / UTS #39 17.0.0
Source of truth unicode/ in this repository
Runtime download none

Refresh generated maps with npm run generate (writes JavaScript, Python, and PHP runtime data from the same files).

JavaScript warn() / reject()

These exist only in the JavaScript browser build. They attach form metadata or constraint validation from detect(). Visitor-facing reject() messages are ordinary validation text, not “phishing” warnings.

Development

npm install
npm run generate
npm test
npm run build

cd python && python -m build && pytest
composer install && vendor/bin/phpunit -c php/phpunit.xml.dist

License

MIT. Unicode data: Unicode License V3 (see NOTICE).