How to verify the product handle is valid

How to check a string is valid product handle when create product. We need to maintaince the products’ handle outside shopify, but we need to convert the handle to shopify accepted handle format.

I tested it the shopify can contains “-“, “_“, number, letter. The charactor “%“ is not allowed.

But I don’t test all charactors, I can’t find a official document what charactors is allowed in handle. The document in Help Center is saying “A valid URL handle can contain letters, dashes, and numbers, but it can’t contain any spaces.“, but the charactor “_“ is allowed, which is mismatch the document.

You’re right to notice the mismatch Shopify’s documentation doesn’t fully cover all edge cases.

In practice, Shopify “handles” behave like URL slugs and are automatically normalized. Based on common behavior:

  • Allowed: lowercase letters (a–z), numbers (0–9), hyphens (-)
  • Underscores (_) may sometimes work, but they’re not officially documented and aren’t consistently recommended
  • Not allowed: special characters like %, spaces, or symbols
  • these are either removed or converted

If you’re generating handles outside Shopify, the safest approach is to normalize them yourself:

  1. Convert to lowercase
  2. Replace spaces and underscores with hyphens
  3. Remove all special characters
  4. Replace multiple hyphens with a single hyphen

Example (pseudo-format):
My Product_Name 100%my-product-name-100

This ensures consistency with Shopify’s expected URL structure and avoids unexpected behavior.

Since Shopify may still modify the handle during product creation, it’s also a good idea to store and sync the final handle returned by the API.

Unfortunately, there isn’t a fully detailed official character whitelist, so following a strict slug format like this is the most reliable approach.

Hope this helps!

1 Like

Hi @zhlong,

There isn’t an official documentation I’ve found. However we’ve done a good amount of testing and these steps seem to work for us:

  1. Transliterate unicode characters. Eg, Schöne GrößeSchone Grosse. In ruby you can use I18n.transliterate()
  2. Lower-case everything
  3. Remove the following characters: "'\()[]
  4. Anything that isn’t A-Z, a-z, 0-9, or _ becomes a -
  5. Replace any runs of 2+ - with a single - Eg, red--shoe becomes red-shoe
  6. Remove leading or trailing -

It possible this is missing some edge case but it’s worked well for us so far.