PHPackages                             kwi/urllinker - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. kwi/urllinker

ActiveLibrary

kwi/urllinker
=============

Autolink URLs in text or html

357.2k↓100%PHP

Since Sep 23Pushed 6y agoCompare

[ Source](https://github.com/MacDada/UrlLinker)[ Packagist](https://packagist.org/packages/kwi/urllinker)[ RSS](/packages/kwi-urllinker/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

UrlLinker
=========

[](#urllinker)

UrlLinker is a PHP module for converting plain text snippets to HTML, and any web addresses in the text into HTML hyperlinks.

Installing
----------

[](#installing)

1. Download the lib using \[Composer\]():

    > ``composer require kwi/urllinker``
2. In your PHP file require Composer's autoloader:

    > [``](#id1)` &lt;?php
    >
    > require\_once \_\_DIR\_\_.'/vendor/autoload.php'; [``](#id3)[`](#id5)

Usage (procedural API)
----------------------

[](#usage-procedural-api)

> print(htmlEscapeAndLinkUrls($text));

For a longer example, see [UrlLinker-example.php](https://bitbucket.org/kwi/urllinker/src/tip/UrlLinker-example.php).

UrlLinker assumes plain text input, and returns HTML. If your input is already HTML, but it contains URLs that have not been marked up, UrlLinker can handle that as well:

```
print(linkUrlsInTrustedHtml($html));
```

Warning: The latter function must *only* be used on trusted input, as rendering HTML provided by a malicious user can lead to system compromise through [cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). The `htmlEscapeAndLinkUrls` function, on the other hand, can safely be used on untrusted input. (You can remove existing tags from untrusted input via PHP's [strip\_tags](http://php.net/strip-tags) function.)

Usage (object oriented API)
---------------------------

[](#usage-object-oriented-api)

[``](#id10)` $urlLinker = new KwiUrlLinker();

$urlLinker-&gt;linkUrlsAndEscapeHtml($text);

$urlLinker-&gt;linkUrlsInTrustedHtml($html); [``](#id12)[`](#id14)

In your functions, you can depend on UrlLinkerInterface:

[``](#id16)` class Example {

> private $urlLinker;
>
> public function \_\_construct(KwiUrlLinkerInterface $urlLinker) {
>
> > $this-&gt;urlLinker = $urlLinker;
>
> }
>
> public function doStuff($text) {
>
> > // do sth with $text…
> >
> > return $this-&gt;urlLinker-&gt;linkUrlsAndEscapeHtml($text);
>
> }

### }

[](#)

You can configure different options for parsing URLs by passing them into UrlLinker's constructor:

[``](#id19)` // Ftp addresses like "ftp://example.com" will be allowed: $urlLinker = new KwiUrlLinker(true);

// Uppercase URL schemes like "" will be allowed: $urlLinker = new KwiUrlLinker(false, true); [``](#id21)[`](#id23)

Recognized addresses
--------------------

[](#recognized-addresses)

- Web addresses
    - Recognized URL schemes: "http" and "https"
        - The `http://` prefix is optional.
        - Support for additional schemes, e.g. "ftp", can easily be added by tweaking `$rexScheme`.
        - The scheme must be written in lower case. This requirement can be lifted by adding an `i` (the `PCRE_CASELESS` modifier) to `$rexUrlLinker`.
    - Hosts may be specified using domain names or IPv4 addresses.
        - IPv6 addresses are not supported.
    - Port numbers are allowed.
    - Internationalized Resource Identifiers (IRIs) are allowed. Note that the job of converting IRIs to URIs is left to the user's browser.
    - To reduce false positives, UrlLinker verifies that the top-level domain is on the official IANA list of valid TLDs.
        - UrlLinker is updated from time to time as the TLD list is expanded.
        - In the future, this approach may collapse under ICANN's ill-advised new policy of selling arbitrary TLDs for large amounts of cash, but for now it is an effective method of rejecting invalid URLs.
        - Internationalized *top-level* domain names must be written in Punycode in order to be recognized.
        - If you need to support unqualified domain names, such as `localhost`, you may disable the TLD check by 1) replacing `+` with `*` in the `$rexDomain` value and 2) replacing the `if` statement line beneath the "Check that the TLD is valid" comment with `if (true)`. This is obviously a quick-and-dirty hack, and may cause false positives.
- Email addresses
    - Supports the full range of commonly used address formats, including "plus addresses" (as popularized by Gmail).
    - Does not recognized the more obscure address variants that are allowed by the RFCs but never seen in practice.
    - Simplistic spam protection: The at-sign is converted to a HTML entity, foiling naive email address harvesters.
- Addresses are recognized correctly in normal sentence contexts. For instance, in "Visit stackoverflow.com.", the final period is not part of the URL.
- User input is properly sanitized to prevent [cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting) (XSS), and ampersands in URLs are [correctly escaped](http://www.htmlhelp.com/tools/validator/problems.html#amp) as `&amp;` (this does not apply to the `linkUrlsInTrustedHtml` function, which assumes its input to be valid HTML).

Tests
-----

[](#tests)

Unit tests are written using \[PHPUnit\]().

``$ cd PATH_TO_URL_LINKER$ composer install$ phpunit``

Background
----------

[](#background)

A [Stackoverflow.com question](http://stackoverflow.com/questions/1188129/replace-urls-in-text-with-html-links/) prompted me to consider the difficulty of this task. Initially, it seemed easy, but like an itch you just have to scratch, I kept coming back to it, to fix just one more little thing.

Feel free to upvote my answer if you find this code useful.

There's also a [C# implementation](http://codepaste.net/ngamud) by Antoine Sottiau.

Public Domain Dedication
------------------------

[](#public-domain-dedication)

To the extent possible under law, the author has waived all copyright and related or neighboring rights to UrlLinker.

For more information see:

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity28

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 Bus Factor1

Top contributor holds 53.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/130973ac364090f63669aa97c21083ed29f4448da5417fbb4987d6ca15f65984?d=identicon)[MacDada](/maintainers/MacDada)

---

Top Contributors

[![kwi-dk](https://avatars.githubusercontent.com/u/1167359?v=4)](https://github.com/kwi-dk "kwi-dk (23 commits)")[![MacDada](https://avatars.githubusercontent.com/u/136261?v=4)](https://github.com/MacDada "MacDada (20 commits)")

### Embed Badge

![Health badge](/badges/kwi-urllinker/health.svg)

```
[![Health](https://phpackages.com/badges/kwi-urllinker/health.svg)](https://phpackages.com/packages/kwi-urllinker)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
