strip_tags
Removes HTML, XML and PHP tags from a string, optionally keeping a list of allowed tags.
strip_tags(string $string, array|string|null $allowed_tags = null): string- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The input string. |
$allowed_tagsoptional | array|string|null= null | Tags that should not be stripped, either as an array of names like ['p','a'] or a string like '<p><a>'. |
Return value
stringThe input string with tags removed.
Changelog
- PHP 8.0.0allowed_tags is nullable.
- PHP 7.4.0allowed_tags also accepts an array of tag names, which avoids the fiddly '<p><a>' string format.
Two more surprises. Text containing a bare < that is immediately followed by a non-space character, such as 5 <10 and up, loses everything from the < onwards because it looks like an unterminated tag. A < followed by whitespace is left alone, so 5 < 10 and up survives unchanged — but do not rely on that spacing quirk; encode literal angle brackets as < instead. And stripping tags glues words together — <li>a</li><li>b</li> becomes ab, so replace block tags with spaces or newlines first if you care about readability.
Example
When to use it
- Generate a plain-text email body or meta description from stored HTML
- Build a short preview snippet for a blog listing page
- Reduce user-submitted rich text to a small allowed subset such as <p><b><i>
Frequently asked questions
Is strip_tags enough to prevent XSS?
No. It keeps attributes on allowed tags, so an allowed <a> or <img> can still carry onclick, onerror or a javascript: URL. Use htmlspecialchars() to display untrusted text, or a dedicated HTML sanitiser if you must keep real markup.
How do I keep some tags with strip_tags?
Pass them as the second argument, either as an array like ['p','a','br'] (PHP 7.4+) or as a string like '<p><a><br>'. List only the non-self-closing form: self-closing XHTML tags are ignored, so '<br>' already allows both <br> and <br/>, while writing '<br/>' in the allowed list does not work.
Why does strip_tags delete text after a less-than sign?
A < that is immediately followed by a non-space character looks like the start of a tag, so everything from there to the next > (or the end of the string) is removed — 'a <b c' loses the tail. A < followed by whitespace is treated as a literal character and is left alone, so 'a < b' comes back unchanged. Do not depend on that distinction: encode literal angle brackets as < and > before stripping.
More examples
Words running together
The first line prints "onetwothree" because the tags carried the visual separation. Inserting a space before stripping restores readable text, which matters for previews and search indexes.
<?php
$html = '<li>one</li><li>two</li><li>three</li>';
echo strip_tags($html), "\n"; // onetwothree
$spaced = str_replace('</li>', "</li> ", $html);
echo trim(strip_tags($spaced)), "\n"; // one two threeStray angle brackets eat text
The first line prints just "5 " because the < is immediately followed by a digit, so everything from there on is treated as an unterminated tag and discarded. The second line survives unchanged: strip_tags treats a < that is followed by whitespace as a literal character, which is why var_dump(strip_tags('a < b')) returns string(5) "a < b". Encoding literal angle brackets as < before stripping keeps the sentence intact in either case.
<?php
echo strip_tags('5 <10 and rising'), "\n"; // "5 " - no space after <
echo strip_tags('5 < 10 and rising'), "\n"; // "5 < 10 and rising" - kept intact
echo strip_tags('<p>5 < 10 and rising</p>'), "\n";
var_dump(strip_tags('a < b')); // string(5) "a < b"Safe display of untrusted input
Allowing <img> lets the onerror attribute through untouched, which is a live XSS vector. htmlspecialchars escapes the angle brackets so the browser shows the markup as text instead of running it.
<?php
$input = '<img src=x onerror="alert(1)">';
echo strip_tags($input), "\n"; // (empty - tag removed)
echo strip_tags($input, '<img>'), "\n"; // handler survives!
echo htmlspecialchars($input, ENT_QUOTES), "\n"; // rendered as text
Discussion