jsguides

String.prototype.substring()

string.substring(start[, end])

The substring() method returns a portion of a string between the start index and the character before the end index. It does not modify the original string—instead, it creates and returns a new string.

Syntax

str.substring(startIndex)
str.substring(startIndex, endIndex)

Parameters

ParameterTypeDescription
startIndexnumberThe index where extraction begins. Characters at this index are included.
endIndexnumberOptional. The index where extraction ends. Characters at this index are excluded.

Return Value

A new string containing the extracted portion. If endIndex is omitted, extraction continues to the end of the string.

Description

The substring() method swaps its arguments if startIndex is greater than endIndex. It treats any value that is NaN or negative as 0. If either index exceeds the string length, they are treated as the string length.

Unlike slice(), substring() does not accept negative indices. For negative index support, use slice() instead.

Examples

Basic usage

const str = "Hello, World!";

console.log(str.substring(0, 5));   // "Hello"
console.log(str.substring(7));      // "World!"
console.log(str.substring(7, 12));  // "World"

Swapping arguments

If startIndex is greater than endIndex, the arguments are automatically swapped. This means substring(5, 0) returns the same result as substring(0, 5), which can be convenient for parsing but may also hide unintended argument order bugs:

const str = "Hello";

console.log(str.substring(5, 0));  // "Hello" — same as substring(0, 5)
console.log(str.substring(2, 5)); // "llo"

Out of bounds indices

Indices beyond the string length are clamped to the length itself. An endIndex of 100 on a five-character string behaves the same as an endIndex of 5. This clamping means you never get an out-of-range error, but it can silently produce shorter results than expected:

const str = "Hello";

console.log(str.substring(0, 100)); // "Hello" — endIndex clamped to string length
console.log(str.substring(5));      // "" — empty string, startIndex equals length
console.log(str.substring(10));     // "" — empty string, startIndex exceeds length

Negative and NaN indices

Negative indices and NaN are treated as 0. This is different from slice(), which interprets negative values as offsets from the end of the string. A non-numeric string argument also coerces to NaN and then to 0, effectively returning the full string:

const str = "Hello";

console.log(str.substring(-3, 2)); // "He" — -3 treated as 0
console.log(str.substring(2, NaN)); // "He" — NaN treated as 0
console.log(str.substring("abc"));  // "Hello" — NaN from string conversion

Extracting a single character

To extract a single character, use the same index for both parameters. The method returns the empty string between those positions, which in the case of adjacent indices is exactly one character. For single-character access, bracket notation str[1] or charAt() are often more direct:

const str = "Hello";

console.log(str.substring(1, 2)); // "e"

substring() vs slice()

substring() and slice() overlap, but they do not behave the same way. substring() treats negative indexes as 0, and it swaps the arguments if the start is greater than the end. That makes it forgiving, but sometimes a little surprising. slice() is more literal about start and end values, and it supports negative indexes for counting from the end.

The best choice depends on what you want to communicate. If you are working with older code or want the clamping behavior, substring() is still fine. If you want negative indexes or a more direct “take this range exactly as written” feel, slice() often reads better.

Common Gotchas

The automatic argument swap is the one behavior that catches people most often. Code like substring(5, 0) does not return an empty string; it returns the same result as substring(0, 5). That is convenient for a few parsing tasks, but it can hide a bug if the code expected strict ordering.

Another detail is that substring() is not a general-purpose validator. Passing a string that becomes NaN still yields 0, so it can quietly return the whole string instead of failing. When input may be messy, validate the indices first so the result does not mask an upstream error.

Common use cases

Removing a prefix or suffix

substring() makes it easy to strip a known-length prefix from a string, such as removing the https:// scheme from a URL. For suffix removal, combine it with the string length to carve out the portion before the trailing segment:

const url = "https://example.com";
const domain = url.substring(8); // "example.com"

const text = "Hello, World!";
const trimmed = text.substring(0, 5); // "Hello"

Extracting between delimiters

A common pattern pairs substring() with indexOf() to extract the portion of a string between two markers, like pulling the username from an email address. The indexOf() call finds the delimiter position, and substring() takes everything before it:

const email = "user@example.com";
const username = email.substring(0, email.indexOf("@")); // "user"

Performance Notes

substring() is fast and widely supported across all JavaScript environments. For most substring extraction tasks, it gets the job done efficiently.

See Also