Skip to content
Free Tool Arena

How-To & Life · Guide · Text & Writing Utilities

How to Convert to snake_case

snake_case vs SCREAMING_SNAKE, PascalCase-to-snake rules, acronym handling, and language conventions (Python, Ruby, DB columns).

Updated April 2026 · 6 min read

snake_case is the naming convention that uses lowercase words joined by underscores. It’s the default for Python functions and variables, Ruby methods, database column names, Rust local variables, and most config files. Converting from other case styles — PascalCase, camelCase, kebab-case, Title Case with Spaces — looks like a one-line regex until you hit acronyms (HTMLParser → html_parser? or h_t_m_l_parser?), numbers embedded in identifiers, and the SCREAMING_SNAKE variant used for constants. This guide covers the canonical conversion rules, how each language’s community treats edge cases, and the regex patterns that produce consistent results.

Advertisement

The four snake variants

  • snake_case — standard lowercase, for names
  • SCREAMING_SNAKE_CASE — uppercase, for constants
  • Title_Snake_Case — rare, sometimes HTTP header-style
  • camel_Snake_Case — very rare, hybrid

From camelCase and PascalCase

The canonical rule: insert an underscore before any uppercase letter preceded by a lowercase letter, then lowercase the whole thing.

str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase()

"camelCase"       -> "camel_case"
"PascalCase"      -> "pascal_case"
"getXMLParser"    -> "get_xml_parser"  ??  (see next section)

The acronym problem

“HTMLParser” is a single concept but three capitals in a row. The naive regex turns it into “htmlparser” (missing the word break) or “h_t_m_l_parser” (too aggressive). The canonical fix inserts underscores at two boundaries:

  • Lowercase → uppercase: “a” → “A”
  • Uppercase + uppercase-then-lowercase: “AB” + “c” at the split
function toSnake(s) {
  return s
    .replace(/([a-z0-9])([A-Z])/g, "$1_$2")
    .replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2")
    .toLowerCase();
}

toSnake("HTMLParser")      // "html_parser"
toSnake("getHTTPResponse") // "get_http_response"
toSnake("APIKey")          // "api_key"
toSnake("iOSVersion")      // "i_os_version"  (edge case!)

The “iOSVersion” case shows the limit: there’s no dictionary-free way to know “iOS” is one acronym. Most codebases work around it by writing IOSVersion oriOsVersion in source.

From kebab-case

Trivial substitution:

str.replace(/-/g, "_").toLowerCase()

"my-variable-name" -> "my_variable_name"

From Title Case or space-separated

str.replace(/\s+/g, "_").toLowerCase()

"Get User Name" -> "get_user_name"

Strip punctuation first for robustness:

str
  .replace(/[^\p{L}\p{N}\s]/gu, "")
  .replace(/\s+/g, "_")
  .toLowerCase()

Numbers in identifiers

Language communities disagree on how to handle digits next to letters:

  • user2FAuser_2_f_a? user_2fa? user2_fa?
  • version2version_2 or version2?

Python’s inflection library usesuser_2fa and version_2. Rails uses the same rule. Go prefers user2fa with no underscore before digits. Pick one and stay consistent.

SCREAMING_SNAKE_CASE for constants

Convert snake_case to screaming by uppercasing:

"max_retry_count".toUpperCase()
// -> "MAX_RETRY_COUNT"

Python, Ruby, JavaScript, Rust, and most C-family languages use SCREAMING_SNAKE for compile-time constants and environment variables. API_KEY, MAX_CONNECTIONS,DEFAULT_TIMEOUT_MS.

Language conventions

  • Python (PEP 8) — snake_case for functions and variables, PascalCase for classes, SCREAMING_SNAKE for module-level constants.
  • Ruby — snake_case for methods and variables, PascalCase for classes and modules, SCREAMING_SNAKE for constants.
  • Rust — snake_case for variables, functions, modules; PascalCase for types; SCREAMING_SNAKE for constants and statics.
  • PHP — snake_case was the historic convention; modern PHP (PSR-1) prefers camelCase for methods.
  • SQL — column names almost universally snake_case. PascalCase and camelCase in column names cause quoting headaches in PostgreSQL especially.

Database column naming

Almost all ORMs expect snake_case column names and auto-map them to camelCase or PascalCase fields in application code. Railsfirst_name column <-> Ruby first_nameattribute. ActiveRecord and SQLAlchemy both do this conversion automatically; mess up the DB casing and you’ll fight the ORM all day.

Environment variables

Conventionally SCREAMING_SNAKE: DATABASE_URL,NODE_ENV, API_KEY. POSIX shells treat variable names as identifiers, so underscores and digits are fine; hyphens are not.

Round-trip considerations

snake_case → camelCase → snake_case usually round-trips cleanly if you avoid acronyms and digit edge cases. Breaking examples:

"html_parser"  -&gt; "htmlParser"  -&gt; "html_parser"   OK
"user_2fa"     -&gt; "user2Fa"     -&gt; "user_2_fa"    NOT OK
"io_s_version" -&gt; "ioSVersion"  -&gt; "io_s_version"  OK
"api_key"      -&gt; "apiKey"      -&gt; "api_key"       OK

Leading-underscore conventions

Python uses _private for module-internal names and__dunder__ for special protocol methods. JavaScript conventionally prefixes private fields with underscore even though the language has real private syntax now. Preserve leading underscores in conversion:

function toSnakePreservePrefix(s) {
  const leading = s.match(/^_+/)?.[0] ?? "";
  const rest = s.slice(leading.length);
  return leading + toSnake(rest);
}

Common mistakes

Using one regex pass and getting “HTMLParser” wrong. Mixing snake and camel in the same codebase because you copy-pasted from sources with different conventions. Using SCREAMING_SNAKE for long identifiers and making them unreadable (a constant named MAX_ALLOWED_RETRY_COUNT_BEFORE_FAILis a code smell, not a convention win). Converting database columns to camelCase and creating quoting headaches in Postgres. And forgetting that acronyms are the forever edge case — pick your rule and document it.

Run the numbers

Snake case converterKebab case converterCase converter

Advertisement

Found this useful?Email