camelCase to snake_case: Converting Between Naming Conventions

A developer's guide to the four major naming conventions and when to use each

๐Ÿช ๐Ÿ ๐Ÿข ๐Ÿ’ป

TL;DR: There are four main naming conventions in programming: camelCase (JavaScript), snake_case (Python), PascalCase (C#), and kebab-case (CSS/URLs). To convert between them, split the name into words, then rejoin using the target convention's rules. Follow whatever your language uses -- don't be the person writing snake_case in JavaScript.

If you have ever had to connect a Python API (which speaks snake_case) to a JavaScript frontend (which speaks camelCase) while mapping the data into a C# model (which insists on PascalCase), you have felt the pain. It is like being a translator at the United Nations, except everyone is arguing about underscores.

Let's break down the four major naming conventions, why they exist, and how to convert between them without losing your mind.

Meet the Four Naming Conventions

camelCase

First word lowercase, every word after that starts with a capital letter. No separators. Think of a camel's humps -- the uppercase letters are the humps.

firstName
getUserProfile
isAuthenticated
maxRetryCount

Who uses it: JavaScript, Java, TypeScript, Swift, Dart. If you write frontend code, this is your daily bread.

PascalCase (a.k.a. UpperCamelCase)

Same as camelCase, but the first word is capitalized too. It is like camelCase dressed up for a job interview.

FirstName
UserProfile
HttpResponse
DatabaseConnection

Who uses it: C# (for almost everything public), Java (class names), TypeScript (interfaces), React (component names).

๐Ÿช camelCase: lowercase hump up hump up. PascalCase: Hump up hump up from the start.

snake_case

All lowercase, words separated by underscores. It slithers along the baseline like a... well, you get it.

first_name
get_user_profile
is_authenticated
max_retry_count

Who uses it: Python, Ruby, Rust, PHP (partially), PostgreSQL. Python's PEP 8 style guide mandates it for functions and variables.

kebab-case

All lowercase, words separated by hyphens. Named after a kebab skewer holding the words together. (Hungry yet?)

first-name
user-profile
is-authenticated
max-retry-count

Who uses it: CSS class names, HTML attributes, URL slugs, CLI arguments (like --dry-run). You cannot use kebab-case for variable names in most languages because the hyphen gets interpreted as a minus sign.

Why did the Python developer break up with the JavaScript developer? Because they had irreconcilable naming_differences. (camelCase just was not their_style.)

Why Do Different Languages Use Different Conventions?

These are not random choices. They evolved from each language's history and culture:

How to Convert Between Conventions

Here is the key insight: every conversion is a two-step process. First, split the input into individual words. Then, rejoin them using the target convention. Once you understand this, it all clicks.

Step 1: Split Into Words

function splitIntoWords(str) {
  return str
    .replace(/([a-z])([A-Z])/g, '$1_$2')       // camelCase boundaries
    .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')  // acronym boundaries
    .split(/[^a-zA-Z0-9]+/)                      // split on non-alphanumeric
    .filter(word => word.length > 0)
    .map(word => word.toLowerCase());
}

// "getUserProfile" -> ["get", "user", "profile"]
// "get_user_profile" -> ["get", "user", "profile"]
// "XMLHttpRequest" -> ["xml", "http", "request"]

The regex magic here inserts underscores at the boundaries between lowercase and uppercase letters, then splits on any non-letter-or-number character. The result is always a clean array of lowercase words, no matter what you feed it.

Step 2: Join in the Target Convention

function toCamelCase(words) {
  return words[0] + words.slice(1)
    .map(w => w[0].toUpperCase() + w.slice(1)).join('');
}

function toPascalCase(words) {
  return words.map(w => w[0].toUpperCase() + w.slice(1)).join('');
}

function toSnakeCase(words) {
  return words.join('_');
}

function toKebabCase(words) {
  return words.join('-');
}
๐Ÿ”„ Split into words, then reassemble. Like LEGO, but for variable names.

The Tricky Edge Cases

Real-world code is messier than textbook examples. Here are the gotchas:

Acronyms: "XMLHttpRequest" is the classic headache. Naive splitting gives you ["X", "M", "L", "Http", "Request"]. The robust regex above treats consecutive uppercase letters as a group, so you correctly get ["XML", "Http", "Request"] which becomes xml_http_request.

Numbers: Identifiers like "h2Database" or "utf8Encode" contain numbers. Your splitter should keep digits attached to adjacent letters: h2_database, utf8_encode.

Single letters: Converting "getX" to snake_case should give you "get_x", not "getx". Make sure your regex catches solo uppercase letters too.

Real-World Scenario: API Boundary Conversion

The most common place you will need this is at the boundary between a backend and frontend. Your Python API sends user_name, but your React app wants userName. Here is a handy recursive key transformer:

function transformKeys(obj, transformFn) {
  if (Array.isArray(obj)) {
    return obj.map(item => transformKeys(item, transformFn));
  }
  if (obj !== null && typeof obj === 'object') {
    return Object.fromEntries(
      Object.entries(obj).map(([key, value]) => [
        transformFn(key),
        transformKeys(value, transformFn)
      ])
    );
  }
  return obj;
}

// Usage
const apiResponse = { user_name: "alice", created_at: "2026-01-01" };
const jsObject = transformKeys(apiResponse, key => {
  const words = splitIntoWords(key);
  return toCamelCase(words);
});
// Result: { userName: "alice", createdAt: "2026-01-01" }

Pro tip: Do the conversion at the API boundary -- once when data comes in, once when it goes out. Never mix naming styles within your codebase. Your future self (and your teammates) will thank you.

Best Practices

  1. Follow your language's convention. Do not use snake_case in JavaScript or camelCase in Python. Your code should feel native to its ecosystem.
  2. Be consistent within a project. If your language does not have a strong convention (looking at you, PHP), pick one and stick with it.
  3. Convert at the boundary. When data crosses between systems, convert at the integration point rather than mixing styles throughout.
  4. Let your linter enforce it. ESLint has camelcase, Pylint has naming-style, RuboCop has Naming/MethodName. Let the machines catch what humans miss.
๐Ÿงน A linter catching naming violations so your code reviewer doesn't have to

Try It Yourself

Paste any identifier or block of text into our Case Converter tool to instantly convert between camelCase, PascalCase, snake_case, kebab-case, UPPER_CASE, and more. Works entirely in your browser.

Open Case Converter →