Skip to main content

change-case vs camelcase vs slugify: String Transformation in JavaScript (2026)

·PkgPulse Team

TL;DR

change-case is the most comprehensive string transformation library — one package that handles every case format (camelCase, PascalCase, kebab-case, snake_case, SCREAMING_SNAKE_CASE, etc.). camelcase is the single-purpose option — just converts strings to camelCase, ~300B, tree-shakable, and Sindre Sorhus quality. slugify converts strings to URL-safe slugs — handles Unicode, transliteration (converting accented chars to ASCII), and special characters. For all-in-one case conversions: change-case. For just camelCase: camelcase. For URL slugs: slugify.

Key Takeaways

  • change-case: ~15M weekly downloads — all case formats in one package, tree-shakable
  • camelcase: ~70M weekly downloads — single-purpose, most popular, Sindre Sorhus
  • slugify: ~5M weekly downloads — URL slugs, Unicode transliteration, SEO-safe
  • Node.js String.prototype.toUpperCase/toLowerCase are built-in — use them for simple cases
  • change-case is modular — import { camelCase } from "change-case" only pulls what you need
  • For API/database field name conversion (snake_case → camelCase), change-case is the standard

PackageWeekly DownloadsBundle SizeAll CasesUnicodeURL Slugs
change-case~15M~30KB total
camelcase~70M~300B❌ camelCase only
slugify~5M~10KB

change-case

change-case — comprehensive case conversion:

All case formats

import {
  camelCase,
  pascalCase,
  snakeCase,
  kebabCase,
  constantCase,
  dotCase,
  pathCase,
  sentenceCase,
  capitalCase,
  noCase,
  trainCase,
} from "change-case"

const input = "hello world foo bar"

camelCase(input)    // "helloWorldFooBar"
pascalCase(input)   // "HelloWorldFooBar"
snakeCase(input)    // "hello_world_foo_bar"
kebabCase(input)    // "hello-world-foo-bar"
constantCase(input) // "HELLO_WORLD_FOO_BAR" (SCREAMING_SNAKE_CASE)
dotCase(input)      // "hello.world.foo.bar"
pathCase(input)     // "hello/world/foo/bar"
sentenceCase(input) // "Hello world foo bar"
capitalCase(input)  // "Hello World Foo Bar"
noCase(input)       // "hello world foo bar" (normalized)
trainCase(input)    // "Hello-World-Foo-Bar" (HTTP header style)

Handles mixed inputs

import { camelCase, snakeCase, kebabCase } from "change-case"

// From snake_case:
camelCase("user_first_name")     // "userFirstName"
camelCase("api_response_data")   // "apiResponseData"

// From camelCase:
snakeCase("userFirstName")       // "user_first_name"
kebabCase("packageHealthScore")  // "package-health-score"

// From PascalCase:
snakeCase("PackageHealthScore")  // "package_health_score"
kebabCase("PackageHealthScore")  // "package-health-score"

// From SCREAMING_SNAKE_CASE:
camelCase("HTTP_STATUS_CODE")    // "httpStatusCode"
camelCase("API_ENDPOINT_URL")    // "apiEndpointUrl"

// From mixed:
camelCase("  hello   world  ")   // "helloWorld" (trims + handles spaces)
camelCase("hello-world_foo.bar") // "helloWorldFooBar" (mixed separators)

Practical use cases

import { camelCase, snakeCase, pascalCase } from "change-case"

// API response normalization — convert snake_case → camelCase:
function normalizeApiResponse<T extends Record<string, unknown>>(data: T) {
  return Object.fromEntries(
    Object.entries(data).map(([key, value]) => [camelCase(key), value])
  )
}

const apiResponse = {
  user_id: "123",
  first_name: "Alice",
  package_health_score: 95,
  is_premium_user: true,
}

normalizeApiResponse(apiResponse)
// { userId: "123", firstName: "Alice", packageHealthScore: 95, isPremiumUser: true }

// Database query — convert camelCase → snake_case for PostgreSQL:
function toDbColumns(obj: Record<string, unknown>) {
  return Object.fromEntries(
    Object.entries(obj).map(([key, value]) => [snakeCase(key), value])
  )
}

// Generate component names from file names:
const fileName = "package-health-card"
pascalCase(fileName)  // "PackageHealthCard" — React component name

// Environment variable names:
constantCase("databaseConnectionString")  // "DATABASE_CONNECTION_STRING"

camelcase

camelcase — single-purpose, Sindre Sorhus quality:

Usage

import camelCase from "camelcase"

// Basic:
camelCase("foo bar")          // "fooBar"
camelCase("foo-bar")          // "fooBar"
camelCase("foo_bar")          // "fooBar"
camelCase("Foo Bar")          // "fooBar"
camelCase("--foo-bar--")      // "fooBar"
camelCase("__foo_bar__")      // "fooBar"
camelCase("FOO_BAR")          // "fooBar"

// PascalCase option:
camelCase("foo bar", { pascalCase: true })  // "FooBar"

// Preserve consecutive uppercase (for acronyms):
camelCase("myURL")            // "myUrl" (default)
camelCase("myURL", { preserveConsecutiveUppercase: true })  // "myURL"

// Multiple words:
camelCase(["foo", "bar"])     // "fooBar"
camelCase(["--foo-bar", "--foo-baz"])  // "fooBarFooBaz"

When camelcase beats change-case

// camelcase is 70M downloads/week vs change-case's 15M
// because it's focused, small, and trusted

// Bundle comparison:
// import camelCase from "camelcase" → 300B
// import { camelCase } from "change-case" → ~5KB (even with tree-shaking)

// For packages or libraries that only need camelCase conversion,
// camelcase is the right choice to minimize bundle size

slugify

slugify — URL-safe string transformation:

Basic usage

import slugify from "slugify"

// Basic slug:
slugify("React vs Vue: A Comprehensive Comparison (2026)")
// "React-vs-Vue-A-Comprehensive-Comparison-2026"

// Lowercase (recommended for URLs):
slugify("React vs Vue: A Comprehensive Comparison (2026)", {
  lower: true,
})
// "react-vs-vue-a-comprehensive-comparison-2026"

// With strict mode (only alphanumeric + separator):
slugify("Hello World! @2026 #npm", { strict: true, lower: true })
// "hello-world-2026-npm"

Unicode transliteration

import slugify from "slugify"

// Converts accented characters to ASCII equivalents:
slugify("Ångström units & schülerschaft", { lower: true })
// "angstrom-units-and-schuleschaft"

slugify("Über alles", { lower: true })
// "uber-alles"

slugify("José García", { lower: true })
// "jose-garcia"

// Chinese/Japanese/Korean — requires locale configuration:
slugify("中文", { locale: "zh", lower: true })
// "zhong-wen"

// Custom character map:
slugify.extend({ "♥": "love", "©": "copyright" })
slugify("I ♥ npm packages © 2026")
// "I-love-npm-packages-copyright-2026"

Blog URL slug generation

import slugify from "slugify"

// Generate SEO-friendly URL slugs:
function generateSlug(title: string, date: string): string {
  const slug = slugify(title, {
    lower: true,
    strict: true,    // Remove special characters
    trim: true,
  })

  // Optional: append date for uniqueness
  // return `${date}-${slug}`
  return slug
}

generateSlug("React vs Vue: Which is Better in 2026?", "2026-03-09")
// "react-vs-vue-which-is-better-in-2026"

generateSlug("Top 10 npm Packages You're Not Using (But Should)", "2026-03-09")
// "top-10-npm-packages-youre-not-using-but-should"

// For Next.js static generation:
export async function generateStaticParams() {
  const posts = await getAllPosts()
  return posts.map((post) => ({
    slug: generateSlug(post.title, post.date),
  }))
}

Feature Comparison

Featurechange-casecamelcaseslugify
camelCase
PascalCase✅ (option)
snake_case
kebab-case
SCREAMING_SNAKE
URL slugs
Unicode transliteration
Special char removal
Bundle size~5KB/fn~300B~10KB
TypeScript
Tree-shakableN/AN/A

When to Use Each

Choose change-case if:

  • You need multiple case formats (not just camelCase)
  • Normalizing API responses (snake_case → camelCase)
  • Generating database column names, environment variables, component names
  • Build tools or code generation where multiple cases are needed

Choose camelcase if:

  • You only need camelCase conversion — no other formats
  • Bundle size is critical — 300B vs 5KB makes a difference in edge environments
  • You want the Sindre Sorhus-quality preserveConsecutiveUppercase option

Choose slugify if:

  • Generating URL-safe slugs for blog posts, product pages, or any URL segment
  • You need Unicode transliteration (accented chars → ASCII)
  • SEO-friendly URL generation in Next.js/Astro/Nuxt content pipelines

Use built-ins for simple cases:

// Don't install a library for simple lowercase/uppercase:
"Hello World".toLowerCase()  // "hello world" — no library needed
"hello world".toUpperCase()  // "HELLO WORLD"

// For title case without a library:
const titleCase = (s: string) =>
  s.replace(/\b\w/g, (c) => c.toUpperCase())
// "hello world" → "Hello World"

Methodology

Download data from npm registry (weekly average, February 2026). Feature comparison based on change-case v5.x, camelcase v8.x, and slugify v1.x.

Compare string utility and JavaScript packages on PkgPulse →

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.