or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# normalize-url

1

2

normalize-url is a comprehensive URL normalization library that standardizes URLs for display, storage, deduplication, sorting, and comparison purposes. It provides extensive configuration options for protocol handling, query parameter management, path cleanup, authentication stripping, and special URL format support including data URLs.

3

4

## Package Information

5

6

- **Package Name**: normalize-url

7

- **Package Type**: npm

8

- **Language**: JavaScript (ES Module)

9

- **Installation**: `npm install normalize-url`

10

11

## Core Imports

12

13

```javascript

14

import normalizeUrl from 'normalize-url';

15

```

16

17

For Node.js environments requiring CommonJS compatibility, you'll need to use dynamic imports:

18

19

```javascript

20

const { default: normalizeUrl } = await import('normalize-url');

21

```

22

23

For TypeScript projects:

24

25

```typescript

26

import normalizeUrl, { Options } from 'normalize-url';

27

```

28

29

## Basic Usage

30

31

```javascript

32

import normalizeUrl from 'normalize-url';

33

34

// Basic normalization

35

const url1 = normalizeUrl('sindresorhus.com');

36

// => 'http://sindresorhus.com'

37

38

// Advanced normalization with options

39

const url2 = normalizeUrl('//www.sindresorhus.com:80/../baz?b=bar&a=foo', {

40

stripWWW: true,

41

removeTrailingSlash: true,

42

sortQueryParameters: true

43

});

44

// => 'http://sindresorhus.com/baz?a=foo&b=bar'

45

46

// Custom configuration

47

const url3 = normalizeUrl('https://user:pass@example.com/path/?utm_campaign=test&ref=source', {

48

stripAuthentication: true,

49

removeQueryParameters: [/^utm_\w+/i, 'ref'],

50

forceHttps: true

51

});

52

// => 'https://example.com/path'

53

```

54

55

## Capabilities

56

57

### URL Normalization

58

59

The main function that normalizes URLs according to specified configuration options.

60

61

```typescript { .api }

62

/**

63

* Normalize a URL with comprehensive configuration options

64

* @param url - URL to normalize, including data URLs

65

* @param options - Configuration options for normalization behavior

66

* @returns Normalized URL string

67

*/

68

function normalizeUrl(url: string, options?: Options): string;

69

```

70

71

**Usage Examples:**

72

73

```javascript

74

// Protocol normalization

75

normalizeUrl('sindresorhus.com'); // => 'http://sindresorhus.com'

76

normalizeUrl('//sindresorhus.com'); // => 'http://sindresorhus.com'

77

normalizeUrl('HTTP://EXAMPLE.COM'); // => 'http://example.com'

78

79

// WWW and hostname cleanup

80

normalizeUrl('http://www.example.com'); // => 'http://example.com'

81

normalizeUrl('example.com.'); // => 'http://example.com'

82

83

// Path normalization

84

normalizeUrl('example.com/foo//bar'); // => 'http://example.com/foo/bar'

85

normalizeUrl('example.com/foo/bar/'); // => 'http://example.com/foo/bar'

86

87

// Query parameter handling

88

normalizeUrl('example.com?b=2&a=1'); // => 'http://example.com/?a=1&b=2'

89

normalizeUrl('example.com?utm_campaign=test&foo=bar'); // => 'http://example.com/?foo=bar'

90

```

91

92

### Protocol Options

93

94

Configure how protocols are handled during normalization.

95

96

```typescript { .api }

97

interface ProtocolOptions {

98

/** Default protocol to prepend if missing */

99

defaultProtocol?: 'https' | 'http'; // default: 'http'

100

/** Whether to prepend defaultProtocol to protocol-relative URLs */

101

normalizeProtocol?: boolean; // default: true

102

/** Convert HTTPS URLs to HTTP */

103

forceHttp?: boolean; // default: false

104

/** Convert HTTP URLs to HTTPS (cannot be used with forceHttp) */

105

forceHttps?: boolean; // default: false

106

}

107

```

108

109

**Usage Examples:**

110

111

```javascript

112

// Default protocol

113

normalizeUrl('example.com', { defaultProtocol: 'https' });

114

// => 'https://example.com'

115

116

// Protocol-relative handling

117

normalizeUrl('//example.com', { normalizeProtocol: false });

118

// => '//example.com'

119

120

// Force protocol conversion

121

normalizeUrl('https://example.com', { forceHttp: true });

122

// => 'http://example.com'

123

124

normalizeUrl('http://example.com', { forceHttps: true });

125

// => 'https://example.com'

126

```

127

128

### Authentication and Security Options

129

130

Control how authentication information and protocols are handled.

131

132

```typescript { .api }

133

interface SecurityOptions {

134

/** Remove authentication part of URL */

135

stripAuthentication?: boolean; // default: true

136

/** Remove protocol from URL completely */

137

stripProtocol?: boolean; // default: false

138

}

139

```

140

141

**Usage Examples:**

142

143

```javascript

144

// Authentication stripping (default behavior)

145

normalizeUrl('https://user:password@example.com');

146

// => 'https://example.com'

147

148

// Keep authentication

149

normalizeUrl('https://user:password@example.com', { stripAuthentication: false });

150

// => 'https://user:password@example.com'

151

152

// Remove protocol entirely

153

normalizeUrl('https://example.com', { stripProtocol: true });

154

// => 'example.com'

155

```

156

157

### Hash and Fragment Options

158

159

Configure handling of URL hashes and text fragments.

160

161

```typescript { .api }

162

interface HashOptions {

163

/** Remove hash from URL */

164

stripHash?: boolean; // default: false

165

/** Remove text fragment part of URL hash */

166

stripTextFragment?: boolean; // default: true

167

}

168

```

169

170

**Usage Examples:**

171

172

```javascript

173

// Text fragment removal (default behavior)

174

normalizeUrl('http://example.com/page#:~:text=hello');

175

// => 'http://example.com/page#'

176

177

normalizeUrl('http://example.com/page#section:~:text=hello');

178

// => 'http://example.com/page#section'

179

180

// Keep text fragments

181

normalizeUrl('http://example.com/page#:~:text=hello', { stripTextFragment: false });

182

// => 'http://example.com/page#:~:text=hello'

183

184

// Remove entire hash

185

normalizeUrl('http://example.com/page#section', { stripHash: true });

186

// => 'http://example.com/page'

187

```

188

189

### Hostname and WWW Options

190

191

Control WWW prefix handling and hostname normalization.

192

193

```typescript { .api }

194

interface HostnameOptions {

195

/** Remove www. from hostname */

196

stripWWW?: boolean; // default: true

197

}

198

```

199

200

**Usage Examples:**

201

202

```javascript

203

// WWW removal (default behavior)

204

normalizeUrl('http://www.example.com'); // => 'http://example.com'

205

206

// Keep WWW

207

normalizeUrl('http://www.example.com', { stripWWW: false });

208

// => 'http://www.example.com'

209

```

210

211

### Query Parameter Options

212

213

Comprehensive query parameter filtering, sorting, and management capabilities.

214

215

```typescript { .api }

216

interface QueryOptions {

217

/** Remove query parameters matching strings/regexes or all if true */

218

removeQueryParameters?: ReadonlyArray<RegExp | string> | boolean; // default: [/^utm_\w+/i]

219

/** Keep only query parameters matching strings/regexes (overrides removeQueryParameters) */

220

keepQueryParameters?: ReadonlyArray<RegExp | string>; // default: undefined

221

/** Sort query parameters alphabetically by key */

222

sortQueryParameters?: boolean; // default: true

223

}

224

```

225

226

**Usage Examples:**

227

228

```javascript

229

// Default UTM parameter removal

230

normalizeUrl('example.com?foo=bar&utm_campaign=test');

231

// => 'http://example.com/?foo=bar'

232

233

// Custom parameter removal

234

normalizeUrl('example.com?foo=bar&ref=source&debug=1', {

235

removeQueryParameters: ['ref', /^debug/i]

236

});

237

// => 'http://example.com/?foo=bar'

238

239

// Remove all parameters

240

normalizeUrl('example.com?foo=bar&baz=qux', { removeQueryParameters: true });

241

// => 'http://example.com'

242

243

// Keep only specific parameters

244

normalizeUrl('example.com?foo=bar&utm_source=google&ref=twitter', {

245

keepQueryParameters: ['foo', /^utm_/]

246

});

247

// => 'http://example.com/?foo=bar&utm_source=google'

248

249

// Disable sorting

250

normalizeUrl('example.com?c=3&a=1&b=2', { sortQueryParameters: false });

251

// => 'http://example.com/?c=3&a=1&b=2'

252

```

253

254

### Path Options

255

256

Control trailing slashes, directory indexes, and path normalization.

257

258

```typescript { .api }

259

interface PathOptions {

260

/** Remove trailing slash from path */

261

removeTrailingSlash?: boolean; // default: true

262

/** Remove sole / pathname */

263

removeSingleSlash?: boolean; // default: true

264

/** Remove directory index files matching patterns */

265

removeDirectoryIndex?: boolean | ReadonlyArray<RegExp | string>; // default: false

266

}

267

```

268

269

**Usage Examples:**

270

271

```javascript

272

// Trailing slash removal (default behavior)

273

normalizeUrl('http://example.com/path/'); // => 'http://example.com/path'

274

275

// Keep trailing slashes

276

normalizeUrl('http://example.com/path/', { removeTrailingSlash: false });

277

// => 'http://example.com/path/'

278

279

// Directory index removal

280

normalizeUrl('http://example.com/index.html', { removeDirectoryIndex: true });

281

// => 'http://example.com'

282

283

normalizeUrl('http://example.com/path/index.php', { removeDirectoryIndex: ['index.php'] });

284

// => 'http://example.com/path'

285

286

// Custom directory index patterns

287

normalizeUrl('http://example.com/default.htm', {

288

removeDirectoryIndex: [/^default\.[a-z]+$/]

289

});

290

// => 'http://example.com'

291

```

292

293

### Port Options

294

295

Configure explicit port number handling.

296

297

```typescript { .api }

298

interface PortOptions {

299

/** Remove explicit port numbers */

300

removeExplicitPort?: boolean; // default: false

301

}

302

```

303

304

**Usage Examples:**

305

306

```javascript

307

// Keep explicit ports (default behavior)

308

normalizeUrl('http://example.com:8080'); // => 'http://example.com:8080'

309

310

// Remove explicit ports

311

normalizeUrl('http://example.com:8080', { removeExplicitPort: true });

312

// => 'http://example.com'

313

314

// Standard ports are always removed

315

normalizeUrl('http://example.com:80'); // => 'http://example.com'

316

normalizeUrl('https://example.com:443'); // => 'https://example.com'

317

```

318

319

### Data URL Support

320

321

Comprehensive support for data URL normalization with MIME type and encoding handling.

322

323

```javascript

324

// Data URL normalization

325

normalizeUrl('data:text/plain,hello'); // => 'data:,hello'

326

normalizeUrl('data:;charset=us-ascii,hello'); // => 'data:,hello'

327

normalizeUrl('data:TEXT/HTML,<h1>Hello</h1>'); // => 'data:text/html,<h1>Hello</h1>'

328

normalizeUrl('data:;base64, SGVsbG8='); // => 'data:;base64,SGVsbG8='

329

330

// Data URLs ignore most normalization options

331

normalizeUrl('data:,example.com/path/', {

332

removeTrailingSlash: true,

333

stripWWW: true

334

}); // => 'data:,example.com/path/' (unchanged)

335

```

336

337

### Custom Protocol Support

338

339

URLs with custom protocols are passed through unchanged to preserve their integrity.

340

341

```javascript

342

// Custom protocols are preserved

343

normalizeUrl('tel:+1234567890'); // => 'tel:+1234567890'

344

normalizeUrl('mailto:user@example.com'); // => 'mailto:user@example.com'

345

normalizeUrl('ftp://files.example.com/path/'); // => 'ftp://files.example.com/path/'

346

normalizeUrl('custom://app.local/resource'); // => 'custom://app.local/resource'

347

```

348

349

## Types

350

351

```typescript { .api }

352

interface Options {

353

/** Default protocol to prepend if missing */

354

readonly defaultProtocol?: 'https' | 'http';

355

/** Whether to prepend defaultProtocol to protocol-relative URLs */

356

readonly normalizeProtocol?: boolean;

357

/** Convert HTTPS URLs to HTTP */

358

readonly forceHttp?: boolean;

359

/** Convert HTTP URLs to HTTPS (cannot be used with forceHttp) */

360

readonly forceHttps?: boolean;

361

/** Remove authentication part of URL */

362

readonly stripAuthentication?: boolean;

363

/** Remove hash from URL */

364

readonly stripHash?: boolean;

365

/** Remove protocol from URL completely */

366

readonly stripProtocol?: boolean;

367

/** Remove text fragment part of URL hash */

368

readonly stripTextFragment?: boolean;

369

/** Remove www. from hostname */

370

readonly stripWWW?: boolean;

371

/** Remove query parameters matching strings/regexes or all if true */

372

readonly removeQueryParameters?: ReadonlyArray<RegExp | string> | boolean;

373

/** Keep only query parameters matching strings/regexes */

374

readonly keepQueryParameters?: ReadonlyArray<RegExp | string>;

375

/** Remove trailing slash from path */

376

readonly removeTrailingSlash?: boolean;

377

/** Remove sole / pathname */

378

readonly removeSingleSlash?: boolean;

379

/** Remove directory index files matching patterns */

380

readonly removeDirectoryIndex?: boolean | ReadonlyArray<RegExp | string>;

381

/** Remove explicit port numbers */

382

readonly removeExplicitPort?: boolean;

383

/** Sort query parameters alphabetically by key */

384

readonly sortQueryParameters?: boolean;

385

}

386

```

387

388

## Error Handling

389

390

The function throws errors in the following cases:

391

392

- **Invalid URLs**: Malformed URLs that cannot be parsed

393

- **Conflicting options**: Using `forceHttp` and `forceHttps` together

394

- **Invalid data URLs**: Malformed data URL format

395

396

```javascript

397

// Error examples

398

try {

399

normalizeUrl('http://'); // Throws: Invalid URL

400

} catch (error) {

401

console.error(error.message); // "Invalid URL: http://"

402

}

403

404

try {

405

normalizeUrl('https://example.com', { forceHttp: true, forceHttps: true });

406

} catch (error) {

407

console.error(error.message); // "The `forceHttp` and `forceHttps` options cannot be used together"

408

}

409

```