String Case Conversion snake_case, camelCase, and Why It Matters in APIs
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:
| Context | Convention | Example | Notes |
|---|---|---|---|
| JavaScript variables / JSON keys | camelCase | userId, firstName | Most REST APIs follow this |
| Python variables / JSON keys | snake_case | user_id, first_name | Django, FastAPI, SQLAlchemy default |
| Class names (most languages) | PascalCase | UserProfile, ApiResponse | Also called UpperCamelCase |
| URL paths | kebab-case | /user-profile, /api-docs | Better SEO than underscores |
| Environment variables | SCREAMING_SNAKE | DATABASE_URL, API_KEY | Universal across shells and CI platforms |
| HTTP headers | Train-Case | Content-Type, X-Api-Key | HTTP/1.1 standard |
| SQL columns / tables | snake_case | user_id, created_at | PostgreSQL, 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.
Install Our Extensions
Add IO tools to your favorite browser for instant access and faster searching
恵 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!
Must-Try Tools
View All New Arrivals
View AllUpdate: Our latest tool was added on Apr 28, 2026
