Regex and cron

Regex for HTML Tags

Find HTML tags in a string for quick cleanup jobs, and know exactly where regex stops being safe.

  • Free foreverNo trial, no paywall, no usage limits.
  • No sign-upOpen the page and start. We never ask for an email to use a tool.
  • PrivateEverything runs in your browser. Your input is never uploaded or stored on our servers.
  • Works offlineOnce the page has loaded, the tool keeps working without a connection.

Pattern

/<\/?([A-Za-z][A-Za-z0-9-]*)(?:\s[^>]*)?\/?>/g
  • g globalFind every match instead of stopping at the first. Needed for matchAll() and for replacing all occurrences.

Regular expression

JavaScript syntax, run by your browser's own engine in a background worker. Press / anywhere to jump here.
Reset to the original pattern and examplesShow cheat sheet: click any token to insert itCopy pattern
Find every match instead of stopping at the first. Needed for matchAll() and for replacing all occurrences.Case-insensitive: /abc/i also matches "ABC" and "aBc".^ and $ match at the start and end of every line, not just the whole string. Use it to test one value per line.Lets . match line breaks too. Without it, . stops at \n and \r.Treats the pattern as Unicode code points: enables \p{…} property escapes and \u{…}, makes emoji count as one character, and rejects sloppy escapes.Only matches starting exactly at lastIndex (position 0 here), never further along. Useful for tokenizers that consume input piece by piece.Records the start and end index of every capture group (match.indices). The tester always shows group positions, so this only changes your code.The upgraded unicode mode (ES2024): set operations like [\p{L}--[a-z]] and [A&&B], string properties like \p{RGI_Emoji}. Cannot be combined with u.
12 matches12 matches · 1 group

Test string

Matches are highlighted as you type, in alternating colors. Click inside a match (or hover its row below) to color its capture groups.
12 matchesClear test string

Explanation

Every part of the pattern in plain English. Hover a row to highlight that part of the pattern.
Copy explanation

Loading the explainer…

Every match with its position and capture groups.Preview a replacement with $1, $<name> and $& references, then copy the result.Copy a ready-to-run snippet for JavaScript, Python, Go, C#, PHP or Dart.

Matches

Named groups are shown by name. undefined means the group did not take part in that match.
Copy matches as JSONDownload matches.csv
#MatchPositionGroups
1<article·class="post">0–22
  • 1article
2<h2>25–29
  • 1h2
3</h2>34–39
  • 1h2
4<p>42–45
  • 1p
5<code>49–55
  • 1code
6</code>66–73
  • 1code
7<br/>91–96
  • 1br
8</p>106–110
  • 1p
9<img·src="cover.webp"·alt=""·/>113–144
  • 1img
10<my-card·data-id="7">147–168
  • 1my-card
11</my-card>168–178
  • 1my-card
12</article>179–189
  • 1article

Need a secure web app built around this? Talk to our team

Quick answer

To find HTML tags, use <\/?([A-Za-z][A-Za-z0-9-]*)(?:\s[^>]*)?\/?> with the g flag. It matches opening, closing and self-closing tags such as <div class="card">, </div> and <br/>, and captures the tag name in group 1. It is fine for quick text cleanup, but use DOMParser or an HTML sanitizer for anything involving untrusted HTML.

  • Tested examples
  • Token-by-token breakdown
  • Code in 5 languages
  • Live tester

How to use the HTML tag regex

  1. 1Copy the pattern with Copy pattern in the tester, or take a snippet for your language from the code section below.
  2. 2Look at the sample in Test string: every HTML tag the regex finds is highlighted.
  3. 3Paste your own text to see the matches, then switch to Replace to preview a replacement.
  4. 4Open the Code tab for JavaScript, Python, Go, C#, PHP or Dart with the pattern translated and escaped.

How does the HTML tag regex work?

Read it left to right. Each piece below matches one part of the input:

  • < The opening angle bracket.
  • \/? An optional slash, for closing tags like </p>.
  • ([A-Za-z][A-Za-z0-9-]*) Group 1, the tag name: a letter, then letters, digits or hyphens (custom elements like my-card).
  • (?:\s[^>]*)? Optionally whitespace and then attributes: anything up to the next >.
  • \/? An optional slash for self-closing syntax like <br/>.
  • > The closing angle bracket.

Flags: g (global).

Which strings does the HTML tag regex match?

The pattern searches inside the text, so a match can be part of a longer string. Every row below is checked against the pattern by our automated test suite before each release.

InputFinds a match?Why
<div>YesA plain opening tag.
</div>YesA closing tag.
<a href="https://example.com">YesAttributes are matched as part of the tag.
<img src="a.png" alt="" />YesSelf-closing with a space before the slash.
<my-card data-id="7">YesCustom element names contain hyphens.
< div>NoA space after < means it is not a tag.
<>NoNo tag name.
<123>NoTag names start with a letter.
<!-- comment -->NoComments are not tags.
5 < 6 and 7 > 3NoComparison operators in text are left alone.

Why should you not parse HTML with regex?

HTML is not a regular language: elements nest to any depth, attribute values can contain >, and browsers repair broken markup in specific, documented ways. A regex sees characters, not structure, so it fails on input like:

  • <a title="x > y"> — the > inside the attribute ends the match early.
  • <script>if (a<b) …</script> — script content is not markup.
  • <div\nclass="x"> — attributes split across lines (this pattern handles that, many do not).

For reading HTML, let the browser parse it:

const doc = new DOMParser().parseFromString(html, "text/html");
const links = [...doc.querySelectorAll("a[href]")].map((a) => a.href);

For untrusted HTML, never strip tags with regex as a security measure: use a sanitizer such as DOMPurify, which is maintained against real XSS bypasses.

How do I strip all tags from a string?

For trusted text where you just want the words, replace every match with nothing:

const text = html.replace(/<\/?([A-Za-z][A-Za-z0-9-]*)(?:\s[^>]*)?\/?>/g, "");

Then decode entities (&amp; → &) with a textarea element or a library. In the browser, new DOMParser().parseFromString(html, "text/html").body.textContent does both jobs correctly in one line, including comments and scripts, so prefer it whenever a DOM is available.

How do I use the HTML tag regex in JavaScript, Python, Go, C# and PHP?

The pattern is translated for each engine rather than pasted as is: named groups, anchors, escapes, shorthand classes and flags are adjusted so each snippet behaves as closely to the JavaScript version as its engine allows. Differences that remain (Go's RE2 has no lookarounds or backreferences, for example) are called out under each one. The Code tab in the tester above also exports Dart, and updates as you edit the pattern.

JavaScript and TypeScript

const regex = /<\/?([A-Za-z][A-Za-z0-9-]*)(?:\s[^>]*)?\/?>/g;
const text = "<div>";

for (const match of text.matchAll(regex)) {
  console.log(match[0], "at index", match.index);
  console.log(match[1]);
}

Python

import re

pattern = re.compile(r"<\/?([A-Za-z][A-Za-z0-9\-]*)(?:\s[^>]*)?\/?>")
text = "<div>"

for match in pattern.finditer(text):
    print(match.group(0), "at index", match.start())
    print(match.groups())

Go

package main

import (
	"fmt"
	"regexp"
)

func main() {
	re := regexp.MustCompile(`<\/?([A-Za-z][A-Za-z0-9\-]*)(?:\s[^>]*)?\/?>`)
	text := "<div>"

	for _, m := range re.FindAllStringSubmatch(text, -1) {
		fmt.Println(m[0])
		fmt.Println(m[1:])
	}
}
  • Go's \s only matches space, \t, \n, \f and \r; JavaScript's also matches the non-breaking space and other Unicode spaces.

C#

using System;
using System.Text.RegularExpressions;

// The timeout stops a pathological input from hanging the thread (ReDoS).
var regex = new Regex(@"<\/?([A-Za-z][A-Za-z0-9\-]*)(?:\s[^>]*)?\/?>", RegexOptions.None, TimeSpan.FromSeconds(1));
var text = "<div>";

foreach (Match match in regex.Matches(text))
{
    Console.WriteLine($"{match.Value} at index {match.Index}");
    Console.WriteLine(match.Groups[1].Value);
}

PHP

<?php

$pattern = '/<\/?([A-Za-z][A-Za-z0-9\-]*)(?:\s[^>]*)?\/?>/';
$text = '<div>';

preg_match_all($pattern, $text, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
foreach ($matches as $match) {
    echo $match[0][0], " at index ", $match[0][1], PHP_EOL;
    echo $match[1][0], PHP_EOL;
}
  • PCRE's \s matches ASCII whitespace unless Unicode properties (UCP) are on; JavaScript's also matches the non-breaking space and other Unicode spaces.

Browse all 25 patterns in the regex pattern library, or build your own in the regex tester.

Frequently asked questions

Replace the tag-name group with the name you want, for example <\/?p(?:\s[^>]*)?> for paragraph tags. Add the i flag, since HTML tag names are case-insensitive.
Only for simple, non-nested cases, using a backreference like <(\w+)[^>]*>[\s\S]*?<\/\1>. Nested elements of the same type break it, which is why a real parser is the right tool.
No. Attackers use malformed markup, event attributes and encoding tricks that regex filters miss. Use a maintained sanitizer such as DOMPurify, or escape text instead of trying to filter markup.

Last updated by the Playxoft engineering team.

From the engineers who built this tool

Building something bigger than a quick fix?

Auth, payments, dashboards and security are where web apps get hard. We have shipped them many times. Share your idea and we will map out a realistic plan and estimate, free and with no obligation.

More free tools

See all tools

Regex Tester

Test regex live with highlighted matches, plain-English explanations and code export.

Open tool

Cron Expression Generator

New

Build and explain cron schedules, see the next runs in any time zone, copy platform snippets.

Open tool

SQL Formatter

Beautify or minify SQL in 12 dialects, with keyword case, indent and line:column errors.

Open tool

cURL to Python Converter

New

Convert cURL commands into Python requests or httpx code with params, json, files and auth.

Open tool

cURL to Fetch Converter

New

Turn any cURL command into JavaScript fetch() code with headers, JSON, forms and auth.

Open tool

cURL to Axios Converter

New

Convert cURL commands into an Axios request config with params, data, auth and timeouts.

Open tool