Signature
strip_tags(string $string, array|string|null $allowed_tags = null): stringPurpose
strip_tags() takes a string and returns a copy with HTML tags, PHP tags, HTML comments and NULL bytes removed. It is a quick way to turn a small piece of markup into plain text, for example when building a short preview or a plain-text fallback. It only removes tag syntax. It does not understand the document, so it is a blunt tool and not a sanitizer.
Signature
Parameters and defaults
$string: the input text to process.$allowed_tags: optional. It lists tags that should survive. The default isnull, which means every tag is removed. You can pass a string such as'<br><a>', or an array of bare tag names such as['br', 'a']. The array form is available from PHP 7.4, andnullis explicitly accepted from PHP 8.0.
HTML comments and PHP tags are always stripped. The allow list cannot change that.
Return value and failure cases
The function always returns a string. It does not return false, and it does not throw an exception for ordinary malformed markup. Its behavior on broken markup is just hard to predict. Tag names longer than 1023 bytes are treated as invalid, whatever the allow list says.
Example 1: removing tags and comments
The first example strips every tag and a comment from a small fragment. Only the text content remains.
$html = '<p>Hello <strong>PHP</strong>!</p><!-- note -->';
echo json_encode(strip_tags($html), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";"Hello PHP!"
Example 2: allowing some tags
The allow list can be a string or an array. Both forms below produce the same result. The <br/> form is kept when br is allowed, so you do not need to list both spellings. The <script> tags are removed, but the text inside them stays in the output.
$html = '<p>Intro<br>line<br/>two <a href="/docs">Docs</a> <script>alert(1)</script></p>';
$result = [
'string' => strip_tags($html, '<br><a>'),
'array' => strip_tags($html, ['br', 'a']),
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"string":"Intro<br>line<br/>two <a href=\"/docs\">Docs</a> alert(1)","array":"Intro<br>line<br/>two <a href=\"/docs\">Docs</a> alert(1)"}
Example 3: entities are left alone
strip_tags() does not decode or encode entities. An existing <b> stays as it is, because it is plain text and not a tag. If the result will be printed inside an HTML page, escape it afterwards with htmlspecialchars().
$input = 'Tom & <i>Jerry</i> <b>';
$stripped = strip_tags($input);
$result = [
'stripped' => $stripped,
'escaped' => htmlspecialchars($stripped),
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"stripped":"Tom & Jerry <b>","escaped":"Tom & Jerry &lt;b&gt;"}
Edge cases
- Content of removed tags remains. Removing
<script>or<style>tags does not remove the code or CSS between them. You get that text as ordinary output, as example 2 shows. - Broken or partial markup. The function does not validate HTML. An unclosed or malformed tag can cause more text to be removed than you expected, because the parser may treat a long stretch of input as still being inside a tag.
- Attributes on allowed tags are untouched. If you allow
<a>, thenonclick,style,href="javascript:..."and any other attribute pass through unchanged. - Self-closing syntax. Allow the non-self-closing name. Listing
<br>covers<br/>too. - NULL bytes in the input are removed along with the tags.
- Whitespace is not tidied. Removing a tag between two words can leave the spaces around it exactly as they were, or join words that had only a tag between them.
Common mistakes
- Using it as XSS protection. The manual warns against this. Output escaping, such as
htmlspecialchars()for HTML text contexts, is the appropriate tool. Which escaping you need depends on where the value is printed. - Allowing tags and assuming they are safe. An allowed
<a>or<img>can still carry dangerous attributes. If you need to allow rich text, use a purpose-built HTML sanitizer that filters attributes too. - Passing angle brackets in an array. With the array form, write
['p', 'a'], not['<p>', '<a>']. - Expecting readable text from complex HTML. Stripping tags does not insert line breaks for block elements and does not decode entities. Paragraphs can run together.
- Stripping before storing and trusting the result forever. Treat the stripped value as plain text and escape it for each output context.
- Forgetting that script text survives. If you remove
<script>tags, the code inside is now visible text. That is harmless as text, but it is probably not what you want to show users.
Related functions
htmlspecialchars()escapes special characters so they display as text. This is the usual output-safety step.html_entity_decode()turns entities back into characters, which is useful if you need readable plain text after stripping.nl2br()converts newlines into<br>tags when you want to display plain text as HTML.preg_replace()gives you full control when you need a custom pattern, though it is a poor choice for parsing HTML in general.
Recap
strip_tags() removes HTML tags, PHP tags, comments and NULL bytes and returns a string. The optional allow list takes a string like '<br><a>' or an array like ['br', 'a']. It does not validate markup, does not clean attributes on allowed tags, leaves entities as they are and keeps the text inside removed tags. Use it for simple text extraction. For safe output, escape the final value for the context where it will be printed.
Tested examples
$html = '<p>Hello <strong>PHP</strong>!</p><!-- note -->';
echo json_encode(strip_tags($html), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";"Hello PHP!"
$html = '<p>Intro<br>line<br/>two <a href="/docs">Docs</a> <script>alert(1)</script></p>';
$result = [
'string' => strip_tags($html, '<br><a>'),
'array' => strip_tags($html, ['br', 'a']),
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"string":"Intro<br>line<br/>two <a href=\"/docs\">Docs</a> alert(1)","array":"Intro<br>line<br/>two <a href=\"/docs\">Docs</a> alert(1)"}
$input = 'Tom & <i>Jerry</i> <b>';
$stripped = strip_tags($input);
$result = [
'stripped' => $stripped,
'escaped' => htmlspecialchars($stripped),
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"stripped":"Tom & Jerry <b>","escaped":"Tom & Jerry &lt;b&gt;"}