Don't like ads? Go Ad-Free Today

String Case Conversion snake_case, camelCase, and Why It Matters in APIs

Published on
String Case Conversion: snake_case, camelCase, and Why It Matters in APIs 1
ADVERTISEMENT · REMOVE?

String casing is one of those things developers don’t think about until it silently breaks something in production. A JavaScript frontend sends userId but the Python backend expects user_id. An ORM quietly renames your SQL column. A CI job fails because an env var was spelled wrong.

Case conventions exist because different languages, frameworks, and systems evolved separately — each with their own idioms. Understanding which format belongs where, and knowing how to convert between them, is a practical skill that saves debugging time.

The main case formats

Here’s a quick rundown of what you’ll encounter in the wild, and where each format is the right choice:

ContextConventionExampleNotes
JavaScript variables / JSON keyscamelCaseuserId, firstNameMost REST APIs follow this
Python variables / JSON keyssnake_caseuser_id, first_nameDjango, FastAPI, SQLAlchemy default
Class names (most languages)PascalCaseUserProfile, ApiResponseAlso called UpperCamelCase
URL pathskebab-case/user-profile, /api-docsBetter SEO than underscores
Environment variablesSCREAMING_SNAKEDATABASE_URL, API_KEYUniversal across shells and CI platforms
HTTP headersTrain-CaseContent-Type, X-Api-KeyHTTP/1.1 standard
SQL columns / tablessnake_caseuser_id, created_atPostgreSQL, MySQL convention

Why mismatched casing breaks API integrations

The most common source of breakage is the JavaScript/Python boundary. JavaScript ecosystems — React, Node, browser APIs — produce camelCase. Python ecosystems — FastAPI, Django REST Framework, SQLAlchemy — expect snake_case.

When a JavaScript client sends this payload:

{
  "firstName": "Alice",
  "userId": 42
}

A Python server accessing request.json["first_name"] gets a KeyError. No warning, no fallback — just a crash. FastAPI can bridge this with alias_generator = to_camel on Pydantic models, but that’s opt-in configuration most teams don’t set until they hit the bug.

The same problem appears at the JavaScript/GraphQL boundary, between microservices written in different languages, and anywhere you’re deserializing JSON without an explicit field mapping.

Converting programmatically

Most languages have this solved, but the approaches differ.

JavaScript: The cleanest option is change-case (lightweight) or lodash (_.camelCase, _.snakeCase). If you’d rather skip the dependency:

// camelCase → snake_case
const toSnakeCase = str =>
  str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);

toSnakeCase('userName');   // 'user_name'
toSnakeCase('createdAt');  // 'created_at'

Python: The re module handles it, but the single-step version breaks on acronyms like HTTPSProxy. Use the two-step approach:

import re

def to_snake_case(name):
    s1 = re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', name)
    return re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

to_snake_case('userName')    # 'user_name'
to_snake_case('HTTPSProxy')  # 'https_proxy'

Go: The standard library doesn’t include a case converter. github.com/iancoleman/strcase is the common choice:

import "github.com/iancoleman/strcase"

strcase.ToSnake("UserName")  // "user_name"
strcase.ToCamel("user_name") // "UserName"
strcase.ToKebab("UserName")  // "user-name"

If you need a quick conversion without writing code, the IO Tools String Case Converter handles camelCase, PascalCase, snake_case, kebab-case, SCREAMING_SNAKE, and more — no installation required.

Database conventions and ORM pitfalls

SQL databases — PostgreSQL, MySQL, SQLite — conventionally use snake_case for column and table names. user_id, created_at, payment_method. This is the expected format, and raw SQL queries will reflect it.

ORMs often auto-convert between your language’s naming convention and the database’s, which is convenient until it isn’t. Sequelize converts JavaScript camelCase to snake_case by default in some configurations — except when it doesn’t, depending on model options, dialect, or version. Prisma generates camelCase field names that map to snake_case columns. ActiveRecord pluralizes table names and snake_cases everything.

The pragmatic move: be explicit. Define column names in your model definitions rather than relying on auto-conversion. It makes the mapping visible in code review and avoids surprises when you run raw queries or migrate to a different ORM.

URL paths: use kebab-case, not underscores

For URL paths, kebab-case is the clear recommendation. Google’s documentation has historically treated hyphens as word separators and underscores as word joiners. A URL like /string-case-converter signals two distinct words; /string_case_converter reads as one long token.

The practical implication: kebab-case URLs perform better for multi-word keyword targeting in search. It’s not a massive ranking factor, but it costs nothing to get right from day one.

Major APIs agree — GitHub, Stripe, and Twilio all use kebab-case for URL paths. Segments like /api/v1/user-profiles are readable, easy to type, and consistent with web standards.

Configuration files: SCREAMING_SNAKE for env vars, camelCase for YAML

Environment variables universally use SCREAMING_SNAKE_CASE. DATABASE_URL, AWS_SECRET_ACCESS_KEY, REDIS_HOST — this convention holds across Linux, Docker, Kubernetes, and every CI/CD platform you’ll encounter. Shells export variables with this format. Don’t fight it.

YAML configuration files tell a different story. Kubernetes manifests, Docker Compose, and GitHub Actions workflows use camelCase for keys — apiVersion, containerPort, imagePullPolicy. Ansible is the notable exception, using snake_case throughout its task definitions.

The rule here is simple: match the format the tool expects. Don’t try to normalize across all your config files — it creates inconsistency without saving effort.

Getting conversions right

The table above covers most scenarios. The real skill is knowing when a case mismatch causes a runtime error versus when a framework silently handles it. When you’re working across a language boundary, check what your serializer or ORM is doing — don’t assume auto-conversion is happening.

For quick, one-off conversions without writing code, the IO Tools String Case Converter handles all major formats in one place. Paste a string, pick the target format, done.

Want To enjoy an ad-free experience? Go Ad-Free Today

Install Our Extensions

Add IO tools to your favorite browser for instant access and faster searching

Add to Chrome Extension Add to Edge Extension Add to Firefox Extension Add to Opera Extension

Scoreboard Has Arrived!

Scoreboard is a fun way to keep track of your games, all data is stored in your browser. More features are coming soon!

ADVERTISEMENT · REMOVE?
ADVERTISEMENT · REMOVE?
ADVERTISEMENT · REMOVE?

News Corner w/ Tech Highlights

Get Involved

Help us continue providing valuable free tools

Buy me a coffee
ADVERTISEMENT · REMOVE?