The identifier getHTTPResponseCode2Fast written out in seven cases, camelCase to Title Case, after being split into the words get, HTTP, Response, Code, 2 and Fast.
One identifier, seven spellings, and the same six words underneath every one of them. The acronym HTTP and the digit 2 are where converters disagree: a naive regex makes h_t_t_p out of the first, and tools split on opinion about whether the second is a word of its own. Once the words are right, the rest is joining.
13 cases from one paste·XMLHttpRequest → xml_http_request, not x_m_l·Straße stays straße until you ask for strasse·0 bytes uploaded

A case converter has exactly one hard part, and it is not the casing. It is deciding where one word ends and the next begins in XMLHttpRequest, iso8601Date or Größe. Get that split right once and camelCase, snake_case, kebab-case and the other ten are just different ways of gluing the words back together. Most converters get it wrong in the same three places, and those three are the ones this page spends its time on.

The thirteen cases

The names are folklore rather than standard, so two people can mean different things by "camel case". This is what the cards above produce, for the input XMLHttpRequest parser with the default options.

CaseResultAlso called
camelCasexmlHttpRequestParserlower camel case, dromedary case
PascalCaseXmlHttpRequestParserupper camel case, StudlyCaps, CapWords
snake_casexml_http_request_parserunderscore case, pothole case
SCREAMING_SNAKE_CASEXML_HTTP_REQUEST_PARSERCONSTANT_CASE, MACRO_CASE, UPPER_SNAKE
kebab-casexml-http-request-parserdash-case, spinal-case, lisp-case, param-case
Train-CaseXml-Http-Request-ParserHTTP-Header-Case
dot.casexml.http.request.parser
path/casexml/http/request/parser
flatcasexmlhttprequestparserlowercase without separators
Title CaseXMLHttpRequest Parserheadline case, Start Case
Sentence caseXMLHttpRequest parser
lowercasexmlhttprequest parser
UPPERCASEXMLHTTPREQUEST PARSERall caps

Two of those rows deserve a second look. Title Case and Sentence case treat a line that contains spaces as text, not as an identifier. Punctuation stays where it was, all-caps words such as HTTP are left alone, and a word with a capital inside it (XMLHttpRequest, iPhone, macOS) is not lowercased, because every mechanical rule that touches it produces Iphone. An identifier without spaces is split into words first, so user_id still becomes User Id. lowercase and UPPERCASE are the only two that do not split at all. They recase the line and leave every separator as it was, which is what you want for API_KEY and not what you want for apiKey.

COBOL-CASE, the hyphenated capitals, is missing on purpose. Outside COBOL nobody types it, and it would only push a useful card below the fold.

How the converter works

Paste identifiers or text, one per line, and every case appears at once. A whole column of database fields or an entire API response shape is the better use. The "a whole API" preset takes six camelCase keys to snake_case in one paste. Under the input, each line says what it looks like (snake_case, Title Case, mixed separators), so an inconsistent input shows before it is converted. Clicking a card makes that case the big result with its own copy button, and "use as input" feeds a result back in, the quickest way to check that a round trip survives.

The four options each decide one of the splitting questions. --acronyms treats a run of capitals as one word, so XMLHttpRequest becomes xml_http_request and HTTP stays HTTP in Title Case, while off makes every capital start a word. --split-digits decides whether 8601 in iso8601Date is its own word. --ascii transliterates before converting, with the German two-letter spelling for umlauts and ss for ß, and drops whatever is left outside ASCII. --small-words keeps a, of, the and the other short words lowercase inside Title Case, the short words AP and Chicago both lowercase, unless the word comes first or last.

Apostrophes stay in the text cases and vanish in the identifier ones, so don't stop is Don't Stop and dontStop. A leading or trailing underscore survives in the five cases where an underscore is legal identifier syntax (_cache in camelCase, class_ in snake_case) and is dropped in kebab-case and the rest. Everything is computed in your tab as you type, which matters less for a variable name and more for the column list of a production schema.

A table of naming conventions by context: camelCase for JavaScript and Java variables, PascalCase for types, snake_case for Python and SQL, SCREAMING_SNAKE_CASE for constants and environment variables, kebab-case for CSS and URLs, Train-Case for HTTP headers, and the split decision for JSON keys.
Where each case is the convention, with an example that shows the shape. Two rows are the ones worth memorising: SQL columns are snake_case because PostgreSQL folds unquoted identifiers to lowercase and Oracle to uppercase, and Go keeps acronyms in capitals (ServeHTTP, UserID) where every other style guide makes them a word.

Which convention goes where

The choice is almost never yours. Each language settled its conventions decades ago, and the ones that did not (JSON keys) are the ones that cause the arguments. URL slugs are kebab-case too, but with stop words removed and punctuation dropped, which is a job for the slug generator rather than a case converter.

ContextVariables, functionsTypes, classesConstants
JavaScript, TypeScriptcamelCasePascalCaseSCREAMING_SNAKE_CASE
Python (PEP 8)snake_casePascalCase (CapWords)SCREAMING_SNAKE_CASE
Ruby, Rustsnake_casePascalCaseSCREAMING_SNAKE_CASE
PHP (PSR-1, PSR-12)camelCase methods, properties unregulatedPascalCaseSCREAMING_SNAKE_CASE
Java, Kotlin, SwiftcamelCasePascalCaseSCREAMING_SNAKE_CASE (Swift: camelCase)
GocamelCase, PascalCase when exportedPascalCase when exportedsame as variables, MaxInt
C#camelCase locals, PascalCase membersPascalCasePascalCase
SQLsnake_case columns and tables
CSS, HTMLkebab-case properties, classes, attributes--custom-properties
Shell, Docker, CIsnake_case functionsSCREAMING_SNAKE_CASE env vars
URLs, CLI flags, npmkebab-case
HTTP headersTrain-Case by tradition, case-insensitive, lowercase on the wire in HTTP/2
JSON keyscamelCase (Google, Kubernetes) or snake_case (Stripe, GitHub)

SQL is snake_case for a reason that has nothing to do with taste. PostgreSQL folds every unquoted identifier to lowercase and Oracle to uppercase, so createdAt becomes createdat or CREATEDAT unless it is quoted, and a quoted "createdAt" must be quoted in every query forever. Underscores survive the folding, which is why a header row on its way into CSV to SQL is worth running through the snake_case card first. Environment variables are capitals for a similar boring reason. POSIX reserves the uppercase names for the system and its utilities and leaves lowercase to applications.

Go is the odd one out twice. Case is semantics there, not style. A name starting with a capital is exported, a lowercase one is package-private, so PascalCase versus camelCase is decided by visibility and not by kind. And Go keeps acronyms in capitals, which is the next section.

userId or userID

Every style guide agrees that XMLHTTPRequest is unreadable and then disagrees about the fix. Google's Java style guide (section 5.3) says to treat an acronym as a word: XmlHttpRequest, newCustomerId, supportsIpv6OnIos. The Go code review comments say the opposite: ServeHTTP, userID, xmlHTTPRequest, never ServeHttp. Swift's API design guidelines sit with Go for the uppercase form but lowercase the whole acronym when it starts a lowerCamelCase name: URLSession as the type, utf8Bytes as the property. Microsoft's .NET guidelines split by length: two letters stay capitals (System.IO, UI), three or more become a word (XmlReader, HtmlElement), and Id is always a word.

A converter cannot know which guide you follow, but it can at least split the identifier correctly, and that is where most of them fail:

(?=[A-Z]) regex, stringcase 1.2.0
XMLHttpRequest  ->  x_m_l_http_request
userID          ->  user_i_d
getHTTPResponse ->  get_h_t_t_p_response
acronym-aware split
XMLHttpRequest  ->  xml_http_request
userID          ->  user_id
getHTTPResponse ->  get_http_response

The rule on the right is simple to state. A run of capitals is one word, and the last capital of the run starts the next word if a lowercase letter follows it. XMLHttp splits into XML and Http, userID into user and ID. The converter above does this by default, and the --acronyms toggle shows you the naive split if you need to match a tool that does it the other way. Going back into camelCase, the words are joined the Google way (userId, xmlHttpRequest), which is also what lodash and inflection produce. If your codebase is Go, that is the one place where you still edit the result by hand, and the findings row tells you so.

One consequence people hit in reverse. user_id into camelCase is userId, and converting that back to snake_case is user_id again. userID, the Go spelling, also round-trips cleanly. The naive split is the only one that does not, because user_i_d never becomes userID again.

Digits, ß and the Turkish i

Digits have no case, so every converter has to decide whether iso8601Date is two words or three. lodash says three (iso_8601_date), Python's inflection says two (iso8601_date), and a digit followed by a capital is a boundary in both (Code2Fast is code2_fast or code_2_fast, never code2fast). The --split-digits flag picks the side, and the findings row shows both readings when a line contains a digit next to a letter.

Unicode is where the ASCII-only tools quietly destroy data. A converter built on [a-z] and [A-Z] treats Größe as Gr, something, e, and either throws the umlaut away or splits on it. The engine above uses the Unicode categories (\p{Lu}, \p{Ll}, \p{N}), so Straße Größe is straße_größe, which Python 3, Java, JavaScript and PostgreSQL all accept as an identifier. Whether you want that is a separate question, and --ascii answers it the German way: strasse_groesse, with ae, oe, ue rather than the bare vowels a generic diacritic strip produces, and ł, ø, æ mapped to their conventional ASCII spellings instead of being dropped. lodash deburrs the generic way and gives strasse_grosse, so the two agree on ß and disagree on every umlaut. An identifier that looks right and still fails usually carries a character you cannot see, and that is a case for the invisible character detector, not for a case converter.

Two letters break the assumption that upper and lower case have the same length. "ß".toUpperCase() is "SS" in JavaScript, so Straße in UPPERCASE has seven characters and the round trip gives strasse, not straße. And the Turkish i: "I".toLocaleLowerCase("tr") is ı, "i".toLocaleUpperCase("tr") is İ, while the plain toLowerCase() always gives i. The converter uses the locale-independent methods on purpose, so the output does not depend on the language of whoever pastes. Code on a Turkish server with the default locale has no such luxury, which is why "TITLE".toLowerCase() in Java is a known way to break a switch on string constants.

Changing case in code and editors

The reason to know the one-liners is that case conversion belongs in a build step or a serializer, not in a browser tab, once it runs more than once.

WherecamelCase to snake_caseupper, lower, title
JavaScripts.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toLowerCase(), or _.snakeCase from lodashtoUpperCase(), toLowerCase(), _.startCase
Pythonthe same two regexes with re.sub, or inflection.underscore()str.upper(), str.lower(), str.title() (which also gives Don'T)
bashno built-in${var^^}, ${var,,} since bash 4, tr '[:lower:]' '[:upper:]' everywhere, sed 's/.*/\U&/' GNU only
SQLnoneUPPER(), LOWER() everywhere, INITCAP() in PostgreSQL and Oracle, not in MySQL or SQL Server
Excel, Google SheetsnoneUPPER(), LOWER(), PROPER()
VS CodeTransform to Snake Case, Camel Case, Pascal Case, Kebab Case (Command Palette)Transform to Uppercase, Lowercase, Title Case
IntelliJ, PyCharm, WebStorma plugin job (String Manipulation, CamelCase)Toggle Case, Ctrl+Shift+U (Cmd+Shift+U on a Mac)
Vimno built-ingU, gu, ~ over a motion

The JavaScript regex is the one to memorise because it is the acronym-aware split from the section above in two passes: one for a lowercase letter or digit followed by a capital, one for a run of capitals followed by a capital and a lowercase letter. Digits stay glued to the word before them in this version (code2_fast). lodash 4.18 does all of this for you and adds two things you should know about before trusting it in a serializer. It deburrs, so Straße becomes strasse and Größe becomes grosse whether you wanted that or not, and it drops apostrophes, so don't becomes dont, in _.startCase as well.

In a serializer, do not write the regex at all. Jackson has PropertyNamingStrategies.SNAKE_CASE, Pydantic has alias_generator, .NET 8 has JsonNamingPolicy.SnakeCaseLower, and each applies one fixed rule to acronyms that you can test once.

The verdict, and where it is wrong

Use the convention of the language you are writing in and never mix two in one codebase.

Mechanical conversion is wrong in two places: proper nouns, which Title Case and Sentence case cannot recognise (GitHub, van der Berg, Vienna), and acronyms in Go, where userId is wrong and userID is right. Both get finished by hand.

Case questions people search for

What is the difference between camelCase and PascalCase?

The first letter. camelCase starts lowercase (userId, getHttpResponse), PascalCase with a capital (UserId, HttpClient). Otherwise identical: no separators, every new word capitalized.

What is kebab case?

Lowercase words joined with hyphens, like background-color or my-first-post. The name comes from the words looking skewered on the hyphens. It is the convention for CSS properties and classes, URLs, CLI flags (--dry-run), HTML attributes and npm package names. Hyphens make it unusable as an identifier in most programming languages, where a-b is a subtraction, which is why it never competes with snake_case inside code.

Snake case vs camel case, which is better?

Neither, and the question is decided by the language anyway. Python, Ruby, Rust and SQL use snake_case for variables and columns, JavaScript, Java, Kotlin, Swift, C# and PHP methods use camelCase. The two studies everyone cites point in different directions. Binkley et al. (2009) found camelCase identifiers recognised more accurately but more slowly, Sharif and Maletic (2010) found snake_case read faster in an eye-tracking replication, and no style guide has switched because of either. What costs real time is mixing the two in one codebase, or converting mechanically between them in an API layer and getting acronyms wrong on the way.

How do I convert camelCase to snake_case in Python?

Two regex passes, one for acronyms and one for ordinary boundaries: re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", re.sub(r"([A-Z]+)([A-Z][a-z])", r"\1_\2", s)).lower() turns XMLHttpRequest into xml_http_request. The popular one-liner re.sub(r"(?<!^)(?=[A-Z])", "_", s).lower() gives x_m_l_http_request instead, and so does stringcase 1.2.0. With a dependency: inflection 0.5.1 has inflection.underscore("XMLHttpRequest"), which returns xml_http_request, and inflection.camelize(s, False) for the way back.

How do I convert camelCase to snake_case in JavaScript?

Without a library: s.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toLowerCase(). With lodash: _.snakeCase("XMLHttpRequest") is "xml_http_request", and _.camelCase, _.kebabCase and _.startCase are the other directions. Two things lodash 4.18 does surprise people. It deburrs first, so Straße becomes strasse and Größe becomes grosse, and it removes apostrophes, so don't becomes dont.

How do I change case in VS Code?

Open the Command Palette (Ctrl+Shift+P, Cmd+Shift+P on a Mac) with the text selected and run one of the Transform to commands: Uppercase, Lowercase, Title Case, Snake Case, Camel Case, Pascal Case or Kebab Case. They work on every cursor at once, so multi-cursor plus Transform to Snake Case renames a column of identifiers in one go. None of them has a default keybinding, so add one in keyboard shortcuts if you use it daily.

How do I convert text to title case in Excel or Google Sheets?

=PROPER(A1) in both, next to =UPPER() and =LOWER(). PROPER capitalizes the first letter after any non-letter, which bites on apostrophes and hyphens: don't becomes Don'T and o'neil becomes O'Neil. It also has no small-word list, so the of in State of the Art comes out as Of. There is no built-in for camelCase or snake_case in either spreadsheet.

What is screaming snake case?

snake_case in capitals: MAX_RETRIES, DATABASE_URL. Used for constants in most languages, for environment variables, and for C preprocessor macros.

How do I capitalize the first letter of each word in JavaScript?

s.replace(/\b\w/g, (c) => c.toUpperCase()) is the snippet everyone copies, and it has three holes: \w is ASCII only, so école becomes éCole and straße becomes StraßE (ß is not a word character, so the e after it counts as a word start), an apostrophe is a word boundary too, so don't becomes Don'T, and nothing lowercases the rest, so hELLO becomes HELLO. The version that survives all three is s.replace(/[\p{L}\p{N}']+/gu, (w) => w[0].toUpperCase() + w.slice(1).toLowerCase()). In CSS, text-transform: capitalize does the same visually and has the same "rest is not lowercased" behaviour.

Why are CSS properties kebab-case?

Because CSS predates the idea of being written by a programming language, and hyphens were the readable separator that needed no shift key. The cost arrived with the DOM. A hyphen is a minus sign in JavaScript, so the CSSOM maps every property to camelCase (background-color is element.style.backgroundColor) and the same mapping turns data-user-id into dataset.userId. Custom properties keep the hyphens (--main-color) and are read through getPropertyValue, which takes the kebab-case name as a string.

Is JSON camelCase or snake_case?

JSON itself has no rule, so the convention comes from whoever designs the API. Google's JSON style guide and the Kubernetes API use camelCase (apiVersion, creationTimestamp), Stripe and the GitHub REST API use snake_case (payment_method, created_at), and Java and .NET shops often end up with whatever their serializer defaults to. The argument for camelCase is that the main consumer is JavaScript and the keys become plain property names. The argument for snake_case is that the same keys appear in SQL columns, Python code and URLs without conversion. Pick one per API, write it into the style guide, and have the serializer enforce it rather than converting by hand, because the conversion is where userID becomes user_i_d.

What does text-transform: capitalize do differently from uppercase?

uppercase changes every letter. capitalize only uppercases the first letter of each word and leaves the rest exactly as typed, so it cannot fix hELLO, and a word that starts with a digit or an apostrophe is not touched. Both are display-only. The text a user copies out of the page is still the original.