JavaScript String substr() Method

Beginner
⏱️ 9 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Deprecated

What You’ll Learn

String.prototype.substr() extracts characters by start index + length (same API as MDN String.prototype.substr()). Learn why it is deprecated, how negatives work, how it differs from slice() / substring(), five examples, and try-it labs.

01

Kind

Instance method

02

Returns

New string

03

2nd arg

Length

04

Status

Deprecated

05

Mutates?

No

06

Prefer

slice()

Introduction

Need “start here, take this many characters”? That is what substr(start, length) does. It returns a new string and never changes the original.

Today you should reach for slice() instead. substr() is deprecated and optional outside browsers. Still, you will see it in older tutorials and codebases — so it helps to recognize the length-based API.

💡
Beginner tip

substrsubsubstring. sub() builds <sub> HTML. substring() uses two indexes. substr() uses start + length (legacy).

This page is part of JavaScript String Methods. Related topics include slice() and split().

Understanding the substr() Method

str.substr(start, length) copies length characters beginning at start. Omit length to take everything through the end.

  • Returns a new string; the original is unchanged.
  • Negative start counts from the end of the string.
  • Negative length returns "".
  • Prefer slice() for new code.

📝 Syntax

General form of String.prototype.substr:

JavaScript
str.substr(start)
str.substr(start, length)

Parameters

  • start — index of the first character to include. Negatives count from the end. Omitted / undefined treated as 0. NaN treated as 0.
  • length (optional) — how many characters to extract. Omit to go to the end. Negative length returns "". NaN treated as 0.

Return value

A string with the extracted characters:

SituationResult
Normal start + lengthThat many characters from start
Length omittedFrom start to the end
start >= length of stringEmpty string ""
Negative startCount from the end
Negative lengthEmpty string ""

Common patterns

JavaScript
"Mozilla".substr(1, 2);  // "oz"
"Mozilla".substr(2);     // "zilla"
"Mozilla".substr(-3);    // "lla"

// Prefer in new code:
"Mozilla".slice(1, 3);   // "oz"
"Mozilla".slice(2);      // "zilla"
"Mozilla".slice(-3);     // "lla"

⚡ Quick Reference

GoalLegacyPrefer
N chars from indexstr.substr(i, n)str.slice(i, i + n)*
From index to endstr.substr(i)str.slice(i)
Last n charactersstr.substr(-n)str.slice(-n)
Use in new apps?No — use slice()

*Only when n is a non-negative length you control — negative lengths behave differently.

🔍 At a Glance

Four facts to remember about String.substr().

Returns
string

Extracted section

2nd arg
length

Not an end index

Status
deprecated

Annex B legacy

Prefer
slice()

Standard extractor

📋 substr() vs slice() vs substring()

substr()slice()substring()
Second argumentLengthEnd index (exclusive)End index (exclusive)
Negative startFrom endFrom endTreated as 0
Negative 2nd arg""End from endTreated as 0 (may swap)
RecommendationAvoid (legacy)Prefer in new codeOK, less flexible

Examples Gallery

Examples follow MDN String.substr() patterns. Use View Output or Try It Yourself for each case.

📚 Getting Started

Start + length, and omitting the length.

Example 1 — Basic substr()

MDN demo: extract from "Mozilla".

JavaScript
const str = "Mozilla";

str.substr(1, 2);
// "oz"

str.substr(2);
// "zilla"
Try It Yourself

How It Works

substr(1, 2) starts at index 1 and takes 2 characters. Omitting length takes everything from the start index to the end.

Example 2 — MDN Edge Cases

Zero length, past the end, and tiny extracts.

JavaScript
const string = "Mozilla";

string.substr(0, 1);  // "M"
string.substr(1, 0);  // ""
string.substr(1);     // "ozilla"
string.substr(20, 2); // ""
Try It Yourself

How It Works

Length 0 always yields "". Starting past the string length also yields "".

📈 Practical Patterns

Negatives, comparison traps, and migrating to slice.

Example 3 — Negative Start and Length

MDN walkthrough: count from the end; negative length is empty.

JavaScript
const string = "Mozilla";

string.substr(-1, 1);   // "a"
string.substr(1, -1);   // ""
string.substr(-3);      // "lla"
string.substr(-20, 2);  // "Mo"
Try It Yourself

How It Works

A very negative start is clamped to the beginning of the string, so substr(-20, 2) still returns the first two characters.

Example 4 — Why Blind Migration Breaks

MDN warning: substr(a, l) is not always slice(a, a + l).

JavaScript
const str = "01234";
const a = 1;
const l = -2;

str.substr(a, l);       // ""
str.slice(a, a + l);    // "123"
str.substring(a, a + l); // "0"
Try It Yourself

How It Works

When length can be negative, the three methods diverge. Refactor only when you know the ranges of your arguments.

Example 5 — Prefer slice() Helpers

Everyday extracts rewritten the modern way.

JavaScript
function firstN(str, n) {
  return str.slice(0, n);       // was: str.substr(0, n)
}

function fromIndex(str, i) {
  return str.slice(i);          // was: str.substr(i)
}

function lastN(str, n) {
  return str.slice(-n);         // was: str.substr(-n)
}

firstN("CodeToFun", 4);  // "Code"
fromIndex("Mozilla", 2); // "zilla"
lastN("Mozilla", 3);     // "lla"
Try It Yourself

How It Works

For non-negative lengths, slice(start, start + length) matches substr(start, length). Prefer writing the slice form directly.

🚀 Common Use Cases

  • Reading legacy code — recognize start + length extraction.
  • Migrating old scripts — rewrite to slice() carefully.
  • Teaching differences — show length vs end-index APIs.
  • Not for new apps — do not introduce substr() in fresh projects.
  • Not HTML subscript — that is the deprecated sub() wrapper.
  • Not delimiter splits — use split() for CSV / words.

🧠 How substr() Builds the Result

1

Read start / length

Default start to 0; default length to “rest of string.”

Input
2

Normalize negatives

Negative start → from end; negative length → empty result.

Adjust
3

Copy characters

Take up to length characters from the normalized start.

Extract
4

Prefer slice() instead

Use the standard end-index API in new code.

📝 Notes

  • substr() is deprecated (Annex B / web compatibility).
  • The second argument is a length, not an end index.
  • Negative length returns "" — unlike slice.
  • Do not confuse with sub() (HTML) or substring() (two indexes).
  • Blindly replacing with slice(a, a + l) can change behavior.
  • Always capture the return value — the original string is unchanged.

Browser & Runtime Support

String.prototype.substr() is still widely implemented for compatibility, but it is deprecated. Prefer slice() for portable new code.

Deprecated · Annex B

String.substr()

Available in browsers for legacy code. Not part of the main ECMAScript path — use slice() or substring() instead.

Legacy Compatibility only
Google Chrome Supported · Desktop & Mobile
Full support
Mozilla Firefox Supported · Desktop & Mobile
Full support
Apple Safari Supported · macOS & iOS
Full support
Microsoft Edge Supported · Chromium
Full support
Internet Explorer No native support · Use a polyfill
Polyfill
Opera Supported · Modern versions
Full support
Samsung Internet Supported · Android
Full support
Bun Supported · JavaScript runtime
Supported
Deno Supported · JavaScript runtime
Supported
Node.js Supported · Server runtime
Supported
Android WebView Supported · Modern WebView
Full support
substr() Avoid in new code

Bottom line: Recognize substr() in legacy samples. For new extraction, use String.slice() with start/end indexes.

Conclusion

String.prototype.substr() extracts by start and length — a legacy shape that still appears in older code. Learn it to migrate safely, then write new features with slice().

Continue with substring(), slice(), or the String methods hub.

💡 Best Practices

✅ Do

  • Use slice() for new substring extraction
  • Rewrite substr(i) as slice(i)
  • Rewrite substr(-n) as slice(-n)
  • Check length ranges before migrating substr(a, l)
  • Learn substr only to read legacy code

❌ Don’t

  • Add substr() to new production code
  • Confuse substr with sub or substring
  • Assume slice(a, a + l) always matches substr(a, l)
  • Pass negative lengths expecting characters
  • Forget strings are immutable — use the return value

Key Takeaways

Knowledge Unlocked

Five things to remember about String.substr()

Legacy start + length extractor — prefer slice().

5
Core concepts
🔢 02

2nd arg

length

Rule
⚠️ 03

Status

deprecated

Legacy
04

Prefer

slice()

Modern
05

Mutates

no

Immutable

❓ Frequently Asked Questions

String.prototype.substr(start, length?) returns a new string with length characters beginning at start. The original string is unchanged.
Yes. MDN marks it as deprecated. It lives in ECMAScript Annex B (web compatibility). Prefer String.prototype.slice() or substring() in new code.
In substr(), the second argument is a length (how many characters). In slice() and substring(), the second argument is an end index (exclusive).
A negative start counts from the end of the string — for example "Mozilla".substr(-3) returns "lla". Negative length returns an empty string "".
No. sub() is a deprecated HTML wrapper that builds <sub> markup. substr() extracts characters by start and length.
Not always. When length is negative they differ — substr returns "", while slice(a, a + l) may still return characters. Prefer slice with known non-negative lengths, or rewrite carefully.
Did you know?

substr() is defined in ECMAScript Annex B — features kept mainly for web-browser compatibility. Non-browser runtimes are not required to implement it, which is another reason to prefer slice() for portable code.

More String Methods

Return to the hub for slice, trim, replace, and more.

String methods hub →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful