PHPackages                             stevebauman/purify - 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. [Validation &amp; Sanitization](/categories/validation)
4. /
5. stevebauman/purify

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

stevebauman/purify
==================

An HTML Purifier / Sanitizer for Laravel

v6.3.2(2mo ago)5325.6M—5.3%3815MITPHPPHP &gt;=7.4CI passing

Since May 7Pushed 2mo ago11 watchersCompare

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

READMEChangelog (10)Dependencies (10)Versions (34)Used By (15)

Purify
======

[](#purify)

A Laravel wrapper for [HTMLPurifier](https://github.com/ezyang/htmlpurifier) by [ezyang](https://github.com/ezyang).

[![](https://camo.githubusercontent.com/1c91efdb62b1ae34ac079d5609cc20527b39f1a1686083b9a75812867552affb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f73746576656261756d616e2f7075726966792f72756e2d74657374732e796d6c3f6272616e63683d6d6173746572267374796c653d666c61742d737175617265)](https://github.com/stevebauman/purify/actions)[![](https://camo.githubusercontent.com/ab3dbef7c0a0cca820979bba38633738077b1f5b57e99c3d8c9a45926e27c6a4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f73746576656261756d616e2f7075726966792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/stevebauman/purify)[![](https://camo.githubusercontent.com/9cb4b9dbccc1fafc1f1c0f6ade8e15fe9b03ce148b74bb75f5cf1025a22bc1dd/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73746576656261756d616e2f7075726966792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/stevebauman/purify)[![](https://camo.githubusercontent.com/9f6691c0404271bf063c53b4a0ee8f4d2baacb26c263f074c87df1ff33e8fc79/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f73746576656261756d616e2f7075726966792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/stevebauman/purify)

### Index

[](#index)

- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Configuration](#configuration)
- [Cache](#cache)
- [Practices](#practices)
- [Upgrading from v4 to v5](#upgrading-from-v4-to-v5)
- [Upgrading from v5 to v6](#upgrading-from-v5-to-v6)

### Requirements

[](#requirements)

- PHP &gt;= 7.4
- Laravel &gt;= 7.0

### Installation

[](#installation)

To install Purify, run the following command in the root of your project:

```
composer require stevebauman/purify
```

Then, publish the configuration file using:

```
php artisan vendor:publish --provider="Stevebauman\Purify\PurifyServiceProvider"
```

### Usage

[](#usage)

##### Cleaning a String

[](#cleaning-a-string)

To clean a users input, simply use the clean method:

```
use Stevebauman\Purify\Facades\Purify;

$input = 'alert("Harmful Script"); Test';

// Returns 'Test'
$cleaned = Purify::clean($input);
```

##### Cleaning an Array

[](#cleaning-an-array)

Need to purify an array of user input? Just pass in an array:

```
use Stevebauman\Purify\Facades\Purify;

$array = [
    'alert("Harmful Script"); Test',
    'alert("Harmful Script"); Test',
];

$cleaned = Purify::clean($array);

// array [
//  'Test',
//  'Test',
// ]
var_dump($cleaned);
```

##### Dynamic Configuration

[](#dynamic-configuration)

Need a different configuration for a single input? Pass in a configuration array to the `config` method:

> **Note**: Configuration passed into the config method is **not** merged with your default configuration.

```
use Stevebauman\Purify\Facades\Purify;

$config = ['HTML.Allowed' => 'div,b,a[href]'];

$cleaned = Purify::config($config)->clean($input);
```

### Configuration

[](#configuration)

Inside the configuration file, multiple HTMLPurifier configuration sets can be specified, similar to Laravel's built-in `database`, `mail` and `logging` config. Simply call `Purify::config($name)->clean($input)` to use another set of configuration.

For example, if we need to have a separate configuration for a comment system, we can setup this configuration in the `config/purify.php` file:

```
// config/purify.php

'configs' => [
    // ...

    'comments' => [
        // Some configuration ...
    ],
]
```

Then, utilize it anywhere in your application by its name:

```
use Stevebauman\Purify\Facades\Purify;

$cleanedContent = Purify::config('comments')->clean(request('content'));
```

For HTMLPurifier configuration documentation, please visit the HTMLPurifier Website:

### Cache

[](#cache)

After running Purify once, [HTMLPurifier](https://github.com/ezyang/htmlpurifier) will auto-cache your serialized `definitions` into the `serializer.cache` definition you have configured in `config/purify.php`.

Important

If you have configured Purify to utilize the `CacheDefinitionCache` in the `serializer` option, this command will issue a `Cache::clear()` on the cache driver you have configured it to use.

If you have configured Purify to utilize the `FilesystemDefinitionCache` in the `serializer` option, this command will clear the directory that you have configured it to store in.

It is recommended to setup a unique filesystem path or disk (via `config/filesystems.php`) or cache store (via `config/cache.php`) for Purify if you intended to clear the serialized definitions using this command.

If you ever update the `definitions` configuration option, you must clear this HTMLPurifier cache.

You may do so via a `purify:clear` command:

```
php artisan purify:clear
```

#### Disabling Caching

[](#disabling-caching)

To disable caching all together, you may set the `serializer` path to `null`:

```
// config/purify.php

'serializer' => null,
```

This will cause your definitions to be serialized upon each application request.

This is especially useful when debugging or tweaking definition files to see immediate results.

Important

Caching is recommended in production environments.

### Practices

[](#practices)

If you're looking into sanitization, you're likely wanting to sanitize inputted user HTML content that is then stored in your database to be rendered onto your application.

In this scenario, it's likely best practice to sanitize on the *way out* instead of the on the *way in*. The **database doesn't care what text it contains**.

This way you can allow anything to be inserted in the database, and have strong sanization rules on the way out.

To accomplish this, you may use the provided `PurifyHtmlOnGet` cast class on your Eloquent model:

```
use Stevebauman\Purify\Casts\PurifyHtmlOnGet;

class Post extends Model
{
    // Laravel  PurifyHtmlOnGet::class,
    ];

    // Laravel >= 11.x
    protected function casts()
    {
        return [
            'content' => PurifyHtmlOnGet::class,
        ];
    }
}
```

Or, implement it yourself via an Eloquent attribute mutator:

```
use Stevebauman\Purify\Facades\Purify;

class Post extends Model
{
    public function getContentAttribute($value)
    {
        return Purify::clean($value);
    }
}
```

You can even configure the configuration that is used when casting by appending it's name to the cast:

```
// config/purify.php

'configs' => [
    // ...

    'other' => [
        // Some configuration ...
    ],
]
```

```
// Laravel  PurifyHtmlOnGet::class.':other',
];

// Laravel >= 11.x
protected function casts()
{
    return [
        'content' => PurifyHtmlOnGet::class.':other',
    ];
}
```

This helps tremendously if you change your sanization requirements later down the line, then all rendered content will follow these sanization rules.

If you'd like to purify HTML while setting the value, you can use the inverse `PurifyHtmlOnSet` cast instead.

#### Custom HTML definitions

[](#custom-html-definitions)

The `HTML.Doctype` configuration option denotes the schema to ultimately abide to. You may want to extend these schema definitions to support custom elements or attributes (e.g. `...`, or ``) by specifying a custom HTML element "definitions".

Purify ships with additional HTML5 definitions that HTMLPurifier does not (yet) support of the box (via the `Html5Definition` class).

To create your own HTML definition, create a new class and have it implement `Definition`:

```
namespace App;

use HTMLPurifier_HTMLDefinition;
use Stevebauman\Purify\Definitions\Definition;

class CustomDefinition implements Definition
{
    /**
     * Apply rules to the HTML Purifier definition.
     *
     * @param HTMLPurifier_HTMLDefinition $definition
     *
     * @return void
     */
    public static function apply(HTMLPurifier_HTMLDefinition $definition)
    {
        // Customize the HTML purifier definition.
    }
}
```

Then, reference this class in the `config/purify.php` file in the `definitions` key:

```
// config/purify.php

'definitions' => \App\CustomDefinitions::class,
```

If you'd like to extend the built-in default `Html5Definition`, you can apply it to your custom definition:

```
use Stevebauman\Purify\Definitions\Html5Definition;

class CustomDefinition implements Definition
{
    public static function apply(HTMLPurifier_HTMLDefinition $definition)
    {
        Html5Definition::apply($definition);

        // ...
    }
}
```

##### Basecamp Trix Definition

[](#basecamp-trix-definition)

Here's an example for customizing the definition in order to support Basecamp's Trix WYSIWYG editor (credit to [Antonio Primera](https://github.com/stevebauman/purify/issues/7) &amp; [Daniel Sun](https://github.com/stevebauman/purify/issues/77)):

```
namespace App;

use HTMLPurifier_HTMLDefinition;
use Stevebauman\Purify\Definitions\Definition;

class TrixPurifierDefinitions implements Definition
{
    /**
     * Apply rules to the HTML Purifier definition.
     *
     * @param HTMLPurifier_HTMLDefinition $definition
     *
     * @return void
     */
    public static function apply(HTMLPurifier_HTMLDefinition $definition)
    {
        $definition->addElement('figure', 'Inline', 'Inline', 'Common');
        $definition->addAttribute('figure', 'class', 'Class');
        $definition->addAttribute('figure', 'data-trix-attachment', 'Text');
        $definition->addAttribute('figure', 'data-trix-attributes', 'Text');

        $definition->addElement('figcaption', 'Inline', 'Inline', 'Common');
        $definition->addAttribute('figcaption', 'class', 'Class');
        $definition->addAttribute('figcaption', 'data-trix-placeholder', 'Text');

        $definition->addAttribute('a', 'rel', 'Text');
        $definition->addAttribute('a', 'tabindex', 'Text');
        $definition->addAttribute('a', 'contenteditable', 'Enum#true,false');
        $definition->addAttribute('a', 'data-trix-attachment', 'Text');
        $definition->addAttribute('a', 'data-trix-content-type', 'Text');
        $definition->addAttribute('a', 'data-trix-id', 'Number');

        $definition->addElement('span', 'Block', 'Flow', 'Common');
        $definition->addAttribute('span', 'data-trix-cursor-target', 'Enum#right,left');
        $definition->addAttribute('span', 'data-trix-serialize', 'Enum#true,false');

        $definition->addAttribute('img', 'data-trix-mutable', 'Enum#true,false');
        $definition->addAttribute('img', 'data-trix-store-key', 'Text');
    }
}
```

#### Custom CSS definitions

[](#custom-css-definitions)

It's possible to override the CSS definitions, this allows you to customize what inline styles you allow and their properties and values. This can help fill in missing values for properties such as text-align, which by default is missing start and end values. You can do this by creating a CSS definition.

To create your own CSS definition, create a new class and have it implement `CssDefinition`:

```
namespace App;

use HTMLPurifier_CSSDefinition;
use Stevebauman\Purify\Definitions\CssDefinition;

class CustomCssDefinition implements CssDefinition
{
    /**
     * Apply rules to the CSS Purifier definition.
     *
     * @param HTMLPurifier_CSSDefinition $definition
     *
     * @return void
     */
    public static function apply(HTMLPurifier_CSSDefinition $definition)
    {
        // Customize the CSS purifier definition.
        $definition->info['text-align'] = new \HTMLPurifier_AttrDef_Enum(
            ['right', 'left', 'center', 'start', 'end'],
            false,
        );
    }
}
```

Then, reference this class in the `config/purify.php` file in the `css-definitions` key:

```
// config/purify.php

'css-definitions' => \App\CustomCssDefinition::class,
```

See the class HTMLPurifier\_CSSDefinition in the HTMLPurifier library for other examples of what can be changed.

### Upgrading from v4 to v5

[](#upgrading-from-v4-to-v5)

To upgrade from v4, install the latest version by running the below command in the root of your project:

```
composer require stevebauman/purify
```

Then, navigate into your published `config/purify.php` configuration file and copy the `settings` array -- except for the following keys:

- `HTML.DocType`:
- `Core.Encoding`:
- `Cache.SerializerPath`:

```
'settings' => [
-   'Core.Encoding' => 'utf-8',
-   'Cache.SerializerPath' => storage_path('app/purify'),
-   'HTML.Doctype' => 'XHTML 1.0 Strict',
+   'HTML.Allowed' => 'h1,h2,h3,h4,h5,h6,b,strong,i,em,a[href|title],ul,ol,li,p[style],br,span,img[width|height|alt|src]',
+   'HTML.ForbiddenElements' => '',
+   'CSS.AllowedProperties' => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',
+   'AutoFormat.AutoParagraph' => false,
+   'AutoFormat.RemoveEmpty' => false,
],
```

> **Important**: If you've created a unique storage path for `Cache.SerializerPath`, take note of this as well, so you can migrate it into the new configuration file.

Once copied, delete the `config/purify.php` file, and run the below command:

```
php artisan vendor:publish --provider="Stevebauman\Purify\PurifyServiceProvider"
```

Then, inside the newly published `config/purify.php` configuration file, paste the keys (overwriting the current) into the `configs.default` array:

```
'configs' => [
    'default' => [
        'Core.Encoding' => 'utf-8',
        'HTML.Doctype' => 'HTML 4.01 Transitional',
+       'HTML.Allowed' => 'h1,h2,h3,h4,h5,h6,b,strong,i,em,a[href|title],ul,ol,li,p[style],br,span,img[width|height|alt|src]',
+       'HTML.ForbiddenElements' => '',
+       'CSS.AllowedProperties' => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',
+       'AutoFormat.AutoParagraph' => false,
+       'AutoFormat.RemoveEmpty' => false,
    ],
],
```

If you've created a unique serializer path (previously set via the old `Cache.SerializerPath` configuration key mentioned above), then you may reconfigure this in the new `serializer` configuration key:

```
'serializer' => storage_path('app/purify'),
```

You're all set!

### Upgrading from v5 to v6

[](#upgrading-from-v5-to-v6)

In v6, the HTMLPurifier Serializer storage mechanism was updated for Laravel Vapor support, allowing you to store the serialized HTMLPurifier definitions in a Redis cache, or an external filesystem.

To upgrade from v5, install the latest version by running the below command in the root of your project:

```
composer require stevebauman/purify
```

Then, navigate into your published `config/purify.php` configuration file and replace the `serializer` configuration option with the below:

```
-    'serializer' => storage_path('app/purify'),

+    'serializer' => [
+       'disk' => env('FILESYSTEM_DISK', 'local'),
+       'path' => 'purify',
+       'cache' => \Stevebauman\Purify\Cache\FilesystemDefinitionCache::class,
+    ],
+
+    // 'serializer' => [
+    //    'driver' => env('CACHE_DRIVER', 'file'),
+    //    'cache' => \Stevebauman\Purify\Cache\CacheDefinitionCache::class,
+    // ],
```

This will update the syntax used to control the serializer cache mechanism. You may now uncomment the below `serializer` cache definition if you would like to use a Laravel Cache driver (such as Redis) to store the serialized definitions.

###  Health Score

70

—

ExcellentBetter than 100% of packages

Maintenance88

Actively maintained with recent releases

Popularity66

Solid adoption and visibility

Community38

Small or concentrated contributor base

Maturity74

Established project with proven stability

 Bus Factor1

Top contributor holds 80.3% 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.

###  Release Activity

Cadence

Every ~132 days

Recently: every ~142 days

Total

31

Last Release

61d ago

Major Versions

v1.1.2 → v2.0.02017-09-13

v2.0.2 → v3.0.02019-09-03

v3.0.3 → v4.0.02021-01-07

v4.0.1 → v5.0.02022-08-03

v5.1.1 → v6.0.02023-04-03

PHP version history (3 changes)v1.0.0PHP &gt;=5.4.0

v3.0.0PHP &gt;=7.1

v5.0.0PHP &gt;=7.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/c6dd082636ff8a08df8dfdcd622ea242374d1d76dd33bceec5a6cd3ae26dc24f?d=identicon)[stevebauman](/maintainers/stevebauman)

---

Top Contributors

[![stevebauman](https://avatars.githubusercontent.com/u/6421846?v=4)](https://github.com/stevebauman "stevebauman (216 commits)")[![Propaganistas](https://avatars.githubusercontent.com/u/6680176?v=4)](https://github.com/Propaganistas "Propaganistas (19 commits)")[![StyleCIBot](https://avatars.githubusercontent.com/u/11048387?v=4)](https://github.com/StyleCIBot "StyleCIBot (9 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (4 commits)")[![EdwinHoksberg](https://avatars.githubusercontent.com/u/6866019?v=4)](https://github.com/EdwinHoksberg "EdwinHoksberg (2 commits)")[![joostdebruijn](https://avatars.githubusercontent.com/u/1844089?v=4)](https://github.com/joostdebruijn "joostdebruijn (2 commits)")[![Aterniad](https://avatars.githubusercontent.com/u/10251985?v=4)](https://github.com/Aterniad "Aterniad (2 commits)")[![sajjadhossainshohag](https://avatars.githubusercontent.com/u/63788037?v=4)](https://github.com/sajjadhossainshohag "sajjadhossainshohag (2 commits)")[![austenc](https://avatars.githubusercontent.com/u/575421?v=4)](https://github.com/austenc "austenc (2 commits)")[![tiagomalheiro](https://avatars.githubusercontent.com/u/47261954?v=4)](https://github.com/tiagomalheiro "tiagomalheiro (1 commits)")[![andrzejkupczyk](https://avatars.githubusercontent.com/u/11018286?v=4)](https://github.com/andrzejkupczyk "andrzejkupczyk (1 commits)")[![zschuessler](https://avatars.githubusercontent.com/u/302097?v=4)](https://github.com/zschuessler "zschuessler (1 commits)")[![ashleyshenton](https://avatars.githubusercontent.com/u/26444425?v=4)](https://github.com/ashleyshenton "ashleyshenton (1 commits)")[![darthsoup](https://avatars.githubusercontent.com/u/1668978?v=4)](https://github.com/darthsoup "darthsoup (1 commits)")[![Erulezz](https://avatars.githubusercontent.com/u/6772197?v=4)](https://github.com/Erulezz "Erulezz (1 commits)")[![filippotoso](https://avatars.githubusercontent.com/u/26958813?v=4)](https://github.com/filippotoso "filippotoso (1 commits)")[![kvas-damian](https://avatars.githubusercontent.com/u/2725894?v=4)](https://github.com/kvas-damian "kvas-damian (1 commits)")[![mvanduijker](https://avatars.githubusercontent.com/u/1771206?v=4)](https://github.com/mvanduijker "mvanduijker (1 commits)")[![plmrlnsnts](https://avatars.githubusercontent.com/u/16243345?v=4)](https://github.com/plmrlnsnts "plmrlnsnts (1 commits)")[![spekulatius](https://avatars.githubusercontent.com/u/8433587?v=4)](https://github.com/spekulatius "spekulatius (1 commits)")

---

Tags

html-purifierhtml-sanitizerlaravelphplaravelhtmlPurifiercleanpurifycleanerpurification

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/stevebauman-purify/health.svg)

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

###  Alternatives

[propaganistas/laravel-phone

Adds phone number functionality to Laravel based on Google's libphonenumber API.

3.0k35.7M107](/packages/propaganistas-laravel-phone)[proengsoft/laravel-jsvalidation

Validate forms transparently with Javascript reusing your Laravel Validation Rules, Messages, and FormRequest

1.1k2.3M49](/packages/proengsoft-laravel-jsvalidation)[axlon/laravel-postal-code-validation

Worldwide postal code validation for Laravel and Lumen

3853.3M1](/packages/axlon-laravel-postal-code-validation)[xemlock/htmlpurifier-html5

HTML5 support for HTML Purifier

1052.9M11](/packages/xemlock-htmlpurifier-html5)[laravel-validation-rules/phone

Validate that a phone number is in the correct format

69355.5k](/packages/laravel-validation-rules-phone)[galahad/laravel-addressing

Laravel package providing addressing functionality

70316.6k](/packages/galahad-laravel-addressing)

PHPackages © 2026

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