ByteTips.

Guide

How to Convert Text Case: camelCase, snake_case, and kebab-case

Every codebase mixes naming conventions. Learn the five cases, why each language picks its own, and the edge cases that break naive converters.

October 14, 2026 · 4 min read · Shayan

camelCase, snake_case, kebab-case, PascalCase, SCREAMING_SNAKE_CASE. Every codebase mixes them, every language has its favorites, and every developer has wasted time converting between them by hand. The rules look trivial until you hit an acronym, a number, or an abbreviation — and then your converter quietly produces nonsense. Text case conversion is a small skill, but it touches variable names, file names, API fields, CSS classes, and database columns. Getting it right means understanding how each convention splits words.

The five cases you will meet

Most code uses one of five conventions:

  • camelCase — first word lowercase, every later word capitalized. JavaScript variables and functions.
  • PascalCase — every word capitalized, no separators. Class names and React components.
  • snake_case — all lowercase, words joined by underscores. Python, Ruby, database columns.
  • kebab-case — all lowercase, words joined by hyphens. CSS classes, URLs, file names.
  • SCREAMING_SNAKE_CASE — all uppercase with underscores. Constants and environment variables.

Why each language picks its own

Conventions exist for readability and for tooling. JavaScript uses camelCase because its standard library does, and because hyphens are minus operators — my-variable would be parsed as subtraction. Python's style guide mandates snake_case for functions and variables, so Python code that uses camelCase looks foreign. CSS uses kebab-case because its property names (background-color, font-size) set the pattern. APIs often return snake_case JSON from a Python or Ruby backend while the JavaScript frontend wants camelCase, which is why conversion shows up constantly at system boundaries. The case is not cosmetic: it is part of the interface between two systems.

Converting by hand: split on boundaries

Every converter does the same three steps: split the input into words, normalize each word, then join with the target separator. Splitting is the hard part. Words are separated by underscores, hyphens, spaces, and by case transitions — the boundary between a lowercase letter and an uppercase one. In JavaScript, a short regex handles all of it:

function splitWords(str) {
  return str
    .replace(/([a-z0-9])([A-Z])/g, "$1 $2") // camelCase boundary
    .replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2") // acronym boundary
    .split(/[^a-zA-Z0-9]+/) // separators: _ - space
    .filter(Boolean);
}

splitWords("XMLHttpRequest"); // ["XML", "Http", "Request"]
splitWords("API_response-time"); // ["API", "response", "time"]

Once you have the word list, each case is one join away: camelCase lowercases the first word and capitalizes the rest; snake_case lowercases and joins with underscores; kebab-case lowercases and joins with hyphens.

Edge cases that break naive converters

The simple version fails on real input. Watch for these:

  • Acronyms — XMLHttpRequest should split as XML + Http + Request, not X + M + L + Http + Request. The acronym rule above handles it.
  • Numbers — version2Final splits at letter-digit boundaries differently across converters; decide one behavior and stay consistent.
  • Leading underscores — _privateVar keeps its underscore in some conventions and drops it in others.
  • Single-letter words — a1b and similar identifiers are ambiguous by nature.
  • Non-English text — accented characters and non-Latin scripts need Unicode-aware splitting.

Converting API responses in practice

The most common real-world conversion happens at the boundary between a backend and a frontend. A Python API returns snake_case keys like user_account_id, and the React frontend wants userAccountId. The clean fix is to convert once, at the boundary, in a single helper that walks the response object and converts every key — not scattered through every component. Keep the backend's convention in the database and the API, and the frontend's convention in the UI code, with exactly one conversion layer between them. That way, when a new field appears, it converts automatically, and nobody has to remember which side of the boundary they are on.

Try it

Convert any text between all five casings instantly with the Case Converter — paste once and get camelCase, kebab-case, snake_case, SCREAMING, and PascalCase together. The splitting above is really pattern matching, so the Regex Tester is the place to prototype your own boundary rules. For the full regex walkthrough, see How to Use Regex in JavaScript.

More guides