Claude hallucinates incorrect Punycode encoding for Cyrillic (IDN) domain names

Resolved 💬 5 comments Opened Mar 10, 2026 by talkstream Closed Apr 11, 2026

Description

When asked to generate code involving an Internationalized Domain Name (IDN) with Cyrillic characters, Claude attempts to mentally compute the Punycode encoding rather than using a programmatic conversion tool (Bash). The resulting Punycode is completely incorrect and this is a recurring bug — it has been observed across multiple projects.

This is a recurring issue. It has been observed in at least two separate projects:

  1. Project 1 (current): Domain татьянаголовач.рф — Claude generated xn--80aalcbdogfhcgqgp5l1a.xn--p1ai which decodes to йжлиекшмаекйдцамн.рф (meaningless gibberish)
  2. Project 2 (earlier, different codebase): Claude substituted a real, existing third-party domain in Punycode that belonged to someone else entirely — not gibberish, but an actual stranger's domain. This is potentially a security/legal concern.

Documented case — Project 1

  • Domain: татьянаголовач.рф
  • Correct Punycode: xn--80aaahe2clkb7ab2ewc1b.xn--p1ai
  • Claude's output: xn--80aalcbdogfhcgqgp5l1a.xn--p1ai
  • Claude's output decodes to: йжлиекшмаекйдцамн.рф (meaningless gibberish)

Reproduction

  1. Ask Claude Code to create a website project with a Cyrillic domain name (e.g. татьянаголовач.рф)
  2. Claude will generate config files (astro.config, robots.txt, etc.) with hallucinated Punycode
  3. The generated Punycode looks plausible (starts with xn--80a...) but is completely wrong
  4. Claude even adds a helpful-looking comment // татьянаголовач.рф next to the wrong encoding, creating a false sense of correctness

Evidence from git history

Commit aef267d (initial) → e96c8a3 (fix attempt):

  • Initial commit used wrong Punycode in 4 files (astro.config.mjs, robots.txt, seo.test.ts, PIPELINE.md)
  • Fix commit corrected only 2 of 4 files — Claude didn't grep for all occurrences
  • public/robots.txt still contained wrong Punycode deployed to production
  • The incomplete fix demonstrates a second failure mode: when correcting Punycode, Claude didn't search-and-replace across the entire codebase

Expected behavior

Claude Code has access to Bash — it should use it to compute Punycode programmatically:

node -e "console.log(new URL('http://татьянаголовач.рф').hostname)"
# or
python3 -c "print('татьянаголовач.рф'.encode('idna').decode())"

If for some reason a tool cannot be used, Claude should explicitly warn that it cannot reliably compute Punycode and the user must verify the encoding independently.

Actual behavior

Claude silently generates incorrect Punycode with no warning. The output looks plausible, making it extremely difficult to catch by visual inspection.

Why this is serious

  • SEO breakage: robots.txt Host/Sitemap directives point to non-existent domain
  • Potential security issue: In one case, Claude substituted a real third-party domain, which could lead to unintended traffic routing, cookie/credential leakage, or legal issues
  • Hard to detect: The hallucinated Punycode LOOKS correct (proper xn-- prefix, valid charset, plausible length)
  • Incomplete fixes: Even when the error is caught, Claude may not find/fix all occurrences
  • Affects all non-Latin scripts: Cyrillic, Arabic, Chinese, Korean, etc. domain owners are all at risk

Suggested fix

  • When Claude encounters an IDN domain that needs Punycode conversion, it should always use a Bash tool to perform the conversion programmatically rather than attempting to compute it
  • Add this to Claude's internal guidelines for domain handling
  • Consider a system-level check: if output contains xn-- strings, verify them against the original domain

Environment

  • Claude Code CLI
  • Multiple Claude models across conversations (March 2026)

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗