Convert PascalCase to snake_case

Convert PascalCase class names and type identifiers to snake_case. Ideal for mapping TypeScript or C# class names to Python dataclass fields or PostgreSQL table names.

ZERO UPLOAD · ALL LOCAL
  1. Type or paste text into the input box — all 14 conversions appear instantly.
  2. The Character Case Formats section shows 5 character-level transformations.
  3. The Word Case Formats section shows 9 word-level transformations.
  4. Use the Copy buttons to grab any individual result.
  5. Click "Use as input" to chain conversions (e.g. snake_case → camelCase → kebab-case).

Worked examples for this use case

C# class names → Python dataclass names

Before
UserProfile
OrderLineItem
PaymentMethod
ShippingAddress
After
user_profile
order_line_item
payment_method
shipping_address

TypeScript interface names → SQLAlchemy model names

Before
ProductCatalog
InventoryItem
PriceHistory
After
product_catalog
inventory_item
price_history

INPUT TEXT

CHARACTER CASE FORMATS

lower case
UPPER CASE
Capitalized Case
aLtErNaTiNg cAsE
InVeRsE CaSe

WORD CASE FORMATS

camelCase
PascalCase
snake_case
SCREAMING_SNAKE
kebab-case
dot.case
path/case
sentence case
Title Case

PascalCase to snake_case Converter

PascalCase class names and TypeScript interfaces need to map to snake_case database tables and Python model attributes. "UserProfile" maps to "user_profile", "OrderLineItem" maps to "order_line_item". When you have a schema with dozens of types, this conversion is too error-prone to do manually.

Building on this, the tool splits on every camelCase boundary (the uppercase letter that starts each word) and joins the resulting tokens with underscores in lowercase. It also gives you a reliable list for migrations, models, and API mappings.

When PascalCase meets snake_case in your stack

C# uses PascalCase for all types, methods, and properties per the Microsoft Coding Conventions.1 Python uses snake_case for variables, functions, and class attributes per PEP 8.2 Consequently, when you write a Python client for a C# API (or a Django model that mirrors a C# data contract), every name needs to cross this boundary. TypeScript interfaces also use PascalCase3 and must map to PostgreSQL column names (snake_case) through ORM layer code. Java, Kotlin, and Scala follow the same PascalCase convention for type names, which means this conversion applies at every boundary where a JVM or .NET type name enters a Python or SQL context. gRPC service definitions that serve both C# and Python clients need this conversion on one side or the other to keep the generated code idiomatic in each language.

Edge cases: acronyms and multi-word type names

Acronyms embedded in PascalCase types (like "HTTPRequest" or "UserAPIKey") split at each letter boundary: "HTTPRequest" becomes "h_t_t_p_request" and "UserAPIKey" becomes "user_a_p_i_key". Yet two-letter acronyms like "ID" in "UserID" produce "user_i_d". For cleaner acronym handling, prefer lowercased acronyms in the source: "HttpRequest" converts cleanly to "http_request" and "UserId" converts to "user_id". Numbers inside PascalCase names act as word boundaries: "Form2Submit" becomes "form_2_submit" and "V2Api" becomes "v_2_api". Single-word PascalCase types like "UserProfile" convert cleanly to "user_profile" because the splitter correctly identifies the word boundary between the lowercase prefix and the uppercase second word. When your PascalCase input already contains underscores (which is non-standard), the underscores are preserved as word boundaries alongside the camelCase splits.

Workflow: mapping TypeScript DTOs to Python dataclass fields

Building on this, here is the pattern: copy your TypeScript interface names, one per line, paste into this converter, and copy the snake_case output. Use those names as your Python dataclass class names or attribute groups. CapyToolkit converts each line independently, so a full DTO schema with 20 types processes in one pass.

For SQLAlchemy models, the snake_case class name maps to a snake_case table name by default when you set __tablename__ explicitly or rely on SQLAlchemy's naming convention. When both the TypeScript interface and the Python model share the same base name in their respective conventions, the API contract becomes self-documenting: a developer reading either codebase can trace field names across the boundary without a mapping table. For Pydantic v2 models consumed by FastAPI, the snake_case attribute names serialize to snake_case JSON keys by default4, which matches what the TypeScript DTO expects when the frontend sends data back. The same snake_case output also gives you the Alembic migration column names directly, so your database schema and your Python model stay in lockstep without a separate renaming step.

Generating Alembic migration column names from PascalCase C# class members

Alembic is the database migration tool for SQLAlchemy applications. Column names in Alembic migrations are snake_case by convention, matching the Python attribute names on SQLAlchemy ORM models.5 When you design a Python schema that mirrors a C# data model, converting the C# PascalCase property names to snake_case before writing the migration file prevents naming inconsistencies.

Alembic's op.add_column() function takes the table name and a sa.Column() with the column name as a string. That string must be snake_case to match the SQLAlchemy model attribute. Paste your C# class property names in to keep model and migration column names aligned, then use the snake_case output in both your Alembic migration file and your SQLAlchemy model definition simultaneously.

When the model definition and the migration file drift apart by even a single column name, the ORM layer produces queries that reference a column the database does not have. The resulting error only appears at runtime, not at import time, which makes it tedious to track down in a codebase with dozens of models.

Planning migrations before code review

Alembic's autogenerate mode compares the current SQLAlchemy model definitions against the database schema and generates the migration diff automatically. For autogenerate to work correctly, the column names in the model must match the column names already in the database. If your previous migration used PascalCase column names (non-standard), autogenerate will propose renaming them. Paste the existing column names into this converter to see the correct snake_case equivalents before deciding whether to add a renaming migration step.

Running the converter during the planning phase also makes code review faster. A reviewer who sees snake_case column names in both the model and the migration file knows at a glance that the two are in sync, without tracing each name back to its C# source. Catching a casing mismatch before merge is far cheaper than discovering it after the migration has already applied to a shared staging database. The deterministic output means the same source property always maps to the same column name, so the review is purely a consistency check rather than a recomputation.

Handling C# acronym naming in snake_case output

C# types often contain acronyms like "HTTPRequest" or "UserAPIKey". When converting these to snake_case, each letter of the acronym splits individually: "HTTPRequest" becomes "h_t_t_p_request" and "UserAPIKey" becomes "user_a_p_i_key". These results are technically correct but unreadable in most Python or database contexts. For cleaner results, consider renaming the source type to use title-cased acronyms ("HttpRequest") before conversion, which produces "http_request" as the snake_case output. The same approach works for any multi-letter acronym: "XMLParser" becomes "xml_parser" when the source uses "XmlParser" instead.

Django model verbose_name fields and snake_case display naming

Django model verbose_name fields provide human-readable display names for model fields in the Django admin and in form labels. While the model attribute uses snake_case, the verbose_name is a display string written in lowercase following Django's conventions.6 Django's convention is to write verbose_name as a lowercase string without any prefix capitalization such as verbose_name="user profile", and Django admin capitalizes the first letter automatically in the UI without any extra configuration on your part. The conversion from a C# PascalCase property to a Django_admin-friendly display name is a deliberate two-step process: first convert to snake_case with this tool, then replace underscores with spaces for the verbose_name value.

Batch generating Django field definitions from a C# class is straightforward when you paste all the property names into this converter at once to get the snake_case attribute names. A property like FirstName produces the snake_case attribute first_name and the verbose name "first name" after replacing underscores with spaces. CapyToolkit converts each line independently, so generating attribute names for a 30-field class takes one paste. Write the verbose_name strings separately after replacing underscores with spaces.

Batch generating Django field definitions

When you have a C# class with PascalCase properties and need to write a Django model that mirrors it, paste all the property names into this converter to get the snake_case attribute names. A property like FirstName produces the snake_case attribute first_name and the verbose name "first name" (after replacing underscores with spaces). CapyToolkit converts each line independently, so generating attribute names for a 30-field class takes one paste. Write the verbose_name strings separately after replacing underscores with spaces.

When to use this

Use this when writing Python model classes that mirror C# or TypeScript types, generating PostgreSQL table names from class names, or mapping a PascalCase schema to a snake_case one.

Examples

C# class names → Python dataclass names

Before
UserProfile
OrderLineItem
PaymentMethod
ShippingAddress
After
user_profile
order_line_item
payment_method
shipping_address

TypeScript interface names → SQLAlchemy model names

Before
ProductCatalog
InventoryItem
PriceHistory
After
product_catalog
inventory_item
price_history
Sources
  1. 1.

    Microsoft, "Identifier names - rules and conventions," learn.microsoft.com, accessed June 2026. https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names

  2. 2.

    Guido van Rossum et al., "PEP 8 – Style Guide for Python Code," peps.python.org, 2001. https://peps.python.org/pep-0008/#class-names

  3. 3.

    TypeScript, "Everyday Types," typescriptlang.org, accessed June 2026. https://www.typescriptlang.org/docs/handbook/2/everyday-types.html

  4. 4.

    Pydantic, "Serialization," pydantic.dev, accessed June 2026. https://pydantic.dev/docs/validation/latest/concepts/serialization

  5. 5.

    "Table Configuration with Declarative," SQLAlchemy, docs.sqlalchemy.org, accessed June 2026. https://docs.sqlalchemy.org/en/20/orm/declarative_tables.html

  6. 6.

    "Model field reference," Django Software Foundation, docs.djangoproject.com, accessed June 2026. https://docs.djangoproject.com/en/5.2/ref/models/fields/

FAQ