/^/
MediumValidation5 min read

ISBN-10 / ISBN-13 Regex

Validates the compact, unformatted length and character shape of an ISBN-10 (9 digits plus a final digit or X) or an ISBN-13 (13 digits), without hyphens or spaces.

#isbn#books#validation#publishing#identifier

Regex Pattern

^(?:\d{9}[\dX]|\d{13})$

Default flags: i

Pattern Breakdown

Hover over a token to see what it does.

^(?:\d{9}[\dX]|\d{13})$
TokenMeaning
^Anchors the match to the start of the string
(?:Opens a non-capturing group holding the ISBN-10/ISBN-13 alternation
\d{9}Nine digits: the first 9 digits of an ISBN-10
[\dX]The ISBN-10 check character, which can be a digit or the letter X (representing the value 10)
|Alternation: match either the ISBN-10 branch or the ISBN-13 branch
\d{13}Thirteen digits: a full unhyphenated ISBN-13, including its 978/979 prefix
)Closes the non-capturing alternation group
$Anchors the match to the end of the string

Detailed Explanation

What it does

This pattern accepts two shapes: a 10-character ISBN-10 (9 digits followed by a digit or 'X' check character) or a 13-character ISBN-13 (all digits). It validates length and character composition only, in the compact form without hyphens.

Why it works

ISBN-10 and ISBN-13 are distinguished purely by length and by the fact that only ISBN-10 can end in the letter 'X' (used because the check-digit algorithm can produce a value of 10, which is represented as X). Expressing this as two alternatives inside a non-capturing group lets a single pattern accept both current identifier formats.

Common use cases

  • Validating ISBN input fields on book cataloging, library, or e-commerce forms
  • Filtering bulk-imported publisher metadata for structurally invalid ISBNs
  • Normalizing scraped or OCR'd book data before running full checksum validation
  • Distinguishing ISBN-10 vs ISBN-13 records by matched length before further processing

Edge cases

  • The trailing 'X' in ISBN-10 is only valid as the final character; the 'i' flag also permits lowercase 'x', which many real-world ISBNs use interchangeably
  • Hyphenated or spaced forms like '978-0-306-40615-7' are rejected by this compact pattern since it expects no separators
  • A 13-digit string that doesn't start with 978 or 979 still matches format-wise, even though real ISBN-13s are restricted to those prefixes
  • A structurally valid ISBN-10 or ISBN-13 can still have an incorrect checksum, since this pattern does not perform the modulus arithmetic

Limitations

  • Does not verify the ISBN-10 modulus-11 or ISBN-13 modulus-10 checksum, so it accepts some invalid ISBNs as valid shapes
  • Does not support the hyphenated or space-separated display formats commonly printed on book covers
  • Does not restrict ISBN-13 to the registered 978/979 GS1 prefixes
  • Cannot confirm the ISBN corresponds to a real, published book

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

0306406152 097522980X 097522980x

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const isbnRegex = /^(?:\d{9}[\dX]|\d{13})$/i;
console.log(isbnRegex.test('0306406152')); // true

Common Mistakes

Assuming a regex match guarantees the ISBN checksum is correct

Fix: Run the ISBN-10 modulus-11 or ISBN-13 modulus-10 checksum algorithm in code after the format check passes

Rejecting hyphenated ISBNs shown on real book covers because the compact pattern doesn't allow separators

Fix: Strip hyphens and spaces from user input before validating, or add optional [- ]? separators between groups

Forgetting the case-insensitive flag and rejecting lowercase 'x' check digits

Fix: Use the 'i' flag or uppercase the input first, since both 'X' and 'x' appear in real-world ISBN-10 data

Performance Notes

  • The alternation only has two fixed-length branches, so the engine resolves it in linear time with no backtracking blow-up
  • Anchoring both branches with shared ^ and $ avoids matching an ISBN-shaped substring inside a longer string
  • For bulk catalog validation, precompile the regex once and consider validating length with a cheap string-length check before running the full pattern

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes