{"id":13396659,"url":"https://github.com/sindresorhus/normalize-url","last_synced_at":"2025-05-14T02:05:45.208Z","repository":{"id":25658550,"uuid":"29094022","full_name":"sindresorhus/normalize-url","owner":"sindresorhus","description":"Normalize a URL","archived":false,"fork":false,"pushed_at":"2024-03-10T05:50:56.000Z","size":127,"stargazers_count":847,"open_issues_count":9,"forks_count":123,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-05-12T00:11:17.578Z","etag":null,"topics":["compare-urls","npm-package","sanitize-url","url-normalization"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sindresorhus.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/security.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"sindresorhus","open_collective":"sindresorhus","custom":"https://sindresorhus.com/donate"}},"created_at":"2015-01-11T14:19:55.000Z","updated_at":"2025-05-11T16:37:32.000Z","dependencies_parsed_at":"2022-07-10T12:16:52.988Z","dependency_job_id":"23015058-1edb-4c89-9279-d5f5a5b82a55","html_url":"https://github.com/sindresorhus/normalize-url","commit_stats":{"total_commits":156,"total_committers":44,"mean_commits":"3.5454545454545454","dds":0.3782051282051282,"last_synced_commit":"12e3b1b23730651c8c6c527454da8fd9b4b01738"},"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sindresorhus%2Fnormalize-url","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sindresorhus%2Fnormalize-url/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sindresorhus%2Fnormalize-url/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sindresorhus%2Fnormalize-url/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sindresorhus","download_url":"https://codeload.github.com/sindresorhus/normalize-url/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253851073,"owners_count":21973674,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compare-urls","npm-package","sanitize-url","url-normalization"],"created_at":"2024-07-30T18:00:59.069Z","updated_at":"2025-05-14T02:05:45.168Z","avatar_url":"https://github.com/sindresorhus.png","language":"JavaScript","readme":"# normalize-url [![Coverage Status](https://codecov.io/gh/sindresorhus/normalize-url/branch/main/graph/badge.svg)](https://codecov.io/gh/sindresorhus/normalize-url)\n\n\u003e [Normalize](https://en.wikipedia.org/wiki/URL_normalization) a URL\n\nUseful when you need to display, store, deduplicate, sort, compare, etc, URLs.\n\n**Note:** This package does **not** do URL sanitization. [Garbage in, garbage out.](https://en.wikipedia.org/wiki/Garbage_in,_garbage_out) If you use this in a server context and accept URLs as user input, it's up to you to protect against invalid URLs, [path traversal attacks](https://owasp.org/www-community/attacks/Path_Traversal), etc.\n\n## Install\n\n```sh\nnpm install normalize-url\n```\n\n## Usage\n\n```js\nimport normalizeUrl from 'normalize-url';\n\nnormalizeUrl('sindresorhus.com');\n//=\u003e 'http://sindresorhus.com'\n\nnormalizeUrl('//www.sindresorhus.com:80/../baz?b=bar\u0026a=foo');\n//=\u003e 'http://sindresorhus.com/baz?a=foo\u0026b=bar'\n```\n\n## API\n\n### normalizeUrl(url, options?)\n\nURLs with custom protocols are not normalized and just passed through by default. Supported protocols are: `https`, `http`, `file`, and `data`.\n\nHuman-friendly URLs with basic auth (for example, `user:password@sindresorhus.com`) are not handled because basic auth conflicts with custom protocols. [Basic auth URLs are also deprecated.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#access_using_credentials_in_the_url)\n\n#### url\n\nType: `string`\n\nURL to normalize, including [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs).\n\n#### options\n\nType: `object`\n\n##### defaultProtocol\n\nType: `string`\\\nDefault: `'http'`\\\nValues: `'https' | 'http'`\n\n##### normalizeProtocol\n\nType: `boolean`\\\nDefault: `true`\n\nPrepend `defaultProtocol` to the URL if it's protocol-relative.\n\n```js\nnormalizeUrl('//sindresorhus.com');\n//=\u003e 'http://sindresorhus.com'\n\nnormalizeUrl('//sindresorhus.com', {normalizeProtocol: false});\n//=\u003e '//sindresorhus.com'\n```\n\n##### forceHttp\n\nType: `boolean`\\\nDefault: `false`\n\nNormalize HTTPS to HTTP.\n\n```js\nnormalizeUrl('https://sindresorhus.com');\n//=\u003e 'https://sindresorhus.com'\n\nnormalizeUrl('https://sindresorhus.com', {forceHttp: true});\n//=\u003e 'http://sindresorhus.com'\n```\n\n##### forceHttps\n\nType: `boolean`\\\nDefault: `false`\n\nNormalize HTTP to HTTPS.\n\n```js\nnormalizeUrl('http://sindresorhus.com');\n//=\u003e 'http://sindresorhus.com'\n\nnormalizeUrl('http://sindresorhus.com', {forceHttps: true});\n//=\u003e 'https://sindresorhus.com'\n```\n\nThis option cannot be used with the `forceHttp` option at the same time.\n\n##### stripAuthentication\n\nType: `boolean`\\\nDefault: `true`\n\nStrip the [authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) part of the URL.\n\n```js\nnormalizeUrl('https://user:password@sindresorhus.com');\n//=\u003e 'https://sindresorhus.com'\n\nnormalizeUrl('https://user:password@sindresorhus.com', {stripAuthentication: false});\n//=\u003e 'https://user:password@sindresorhus.com'\n```\n\n##### stripHash\n\nType: `boolean`\\\nDefault: `false`\n\nStrip the hash part of the URL.\n\n```js\nnormalizeUrl('sindresorhus.com/about.html#contact');\n//=\u003e 'http://sindresorhus.com/about.html#contact'\n\nnormalizeUrl('sindresorhus.com/about.html#contact', {stripHash: true});\n//=\u003e 'http://sindresorhus.com/about.html'\n```\n\n##### stripProtocol\n\nType: `boolean`\\\nDefault: `false`\n\nRemove the protocol from the URL: `http://sindresorhus.com` → `sindresorhus.com`.\n\nIt will only remove `https://` and `http://` protocols.\n\n```js\nnormalizeUrl('https://sindresorhus.com');\n//=\u003e 'https://sindresorhus.com'\n\nnormalizeUrl('https://sindresorhus.com', {stripProtocol: true});\n//=\u003e 'sindresorhus.com'\n```\n\n##### stripTextFragment\n\nType: `boolean`\\\nDefault: `true`\n\nStrip the [text fragment](https://web.dev/text-fragments/) part of the URL.\n\n**Note:** The text fragment will always be removed if the `stripHash` option is set to `true`, as the hash contains the text fragment.\n\n```js\nnormalizeUrl('http://sindresorhus.com/about.html#:~:text=hello');\n//=\u003e 'http://sindresorhus.com/about.html#'\n\nnormalizeUrl('http://sindresorhus.com/about.html#section:~:text=hello');\n//=\u003e 'http://sindresorhus.com/about.html#section'\n\nnormalizeUrl('http://sindresorhus.com/about.html#:~:text=hello', {stripTextFragment: false});\n//=\u003e 'http://sindresorhus.com/about.html#:~:text=hello'\n\nnormalizeUrl('http://sindresorhus.com/about.html#section:~:text=hello', {stripTextFragment: false});\n//=\u003e 'http://sindresorhus.com/about.html#section:~:text=hello'\n```\n\n##### stripWWW\n\nType: `boolean`\\\nDefault: `true`\n\nRemove `www.` from the URL.\n\n```js\nnormalizeUrl('http://www.sindresorhus.com');\n//=\u003e 'http://sindresorhus.com'\n\nnormalizeUrl('http://www.sindresorhus.com', {stripWWW: false});\n//=\u003e 'http://www.sindresorhus.com'\n```\n\n##### removeQueryParameters\n\nType: `Array\u003cRegExp | string\u003e | boolean`\\\nDefault: `[/^utm_\\w+/i]`\n\nRemove query parameters that matches any of the provided strings or regexes.\n\n```js\nnormalizeUrl('www.sindresorhus.com?foo=bar\u0026ref=test_ref', {\n\tremoveQueryParameters: ['ref']\n});\n//=\u003e 'http://sindresorhus.com/?foo=bar'\n```\n\nIf a boolean is provided, `true` will remove all the query parameters.\n\n```js\nnormalizeUrl('www.sindresorhus.com?foo=bar', {\n\tremoveQueryParameters: true\n});\n//=\u003e 'http://sindresorhus.com'\n```\n\n`false` will not remove any query parameter.\n\n```js\nnormalizeUrl('www.sindresorhus.com?foo=bar\u0026utm_medium=test\u0026ref=test_ref', {\n\tremoveQueryParameters: false\n});\n//=\u003e 'http://www.sindresorhus.com/?foo=bar\u0026ref=test_ref\u0026utm_medium=test'\n```\n\n##### keepQueryParameters\n\nType: `Array\u003cRegExp | string\u003e`\\\nDefault: `undefined`\n\nKeeps only query parameters that matches any of the provided strings or regexes.\n\n**Note:** It overrides the `removeQueryParameters` option.\n\n```js\nnormalizeUrl('https://sindresorhus.com?foo=bar\u0026ref=unicorn', {\n\tkeepQueryParameters: ['ref']\n});\n//=\u003e 'https://sindresorhus.com/?ref=unicorn'\n```\n\n##### removeTrailingSlash\n\nType: `boolean`\\\nDefault: `true`\n\nRemove trailing slash.\n\n**Note:** Trailing slash is always removed if the URL doesn't have a pathname unless the `removeSingleSlash` option is set to `false`.\n\n```js\nnormalizeUrl('http://sindresorhus.com/redirect/');\n//=\u003e 'http://sindresorhus.com/redirect'\n\nnormalizeUrl('http://sindresorhus.com/redirect/', {removeTrailingSlash: false});\n//=\u003e 'http://sindresorhus.com/redirect/'\n\nnormalizeUrl('http://sindresorhus.com/', {removeTrailingSlash: false});\n//=\u003e 'http://sindresorhus.com'\n```\n\n##### removeSingleSlash\n\nType: `boolean`\\\nDefault: `true`\n\nRemove a sole `/` pathname in the output. This option is independent of `removeTrailingSlash`.\n\n```js\nnormalizeUrl('https://sindresorhus.com/');\n//=\u003e 'https://sindresorhus.com'\n\nnormalizeUrl('https://sindresorhus.com/', {removeSingleSlash: false});\n//=\u003e 'https://sindresorhus.com/'\n```\n\n##### removeDirectoryIndex\n\nType: `boolean | Array\u003cRegExp | string\u003e`\\\nDefault: `false`\n\nRemoves the default directory index file from path that matches any of the provided strings or regexes. When `true`, the regex `/^index\\.[a-z]+$/` is used.\n\n```js\nnormalizeUrl('www.sindresorhus.com/foo/default.php', {\n\tremoveDirectoryIndex: [/^default\\.[a-z]+$/]\n});\n//=\u003e 'http://sindresorhus.com/foo'\n```\n\n##### removeExplicitPort\n\nType: `boolean`\\\nDefault: `false`\n\nRemoves an explicit port number from the URL.\n\nPort 443 is always removed from HTTPS URLs and 80 is always removed from HTTP URLs regardless of this option.\n\n```js\nnormalizeUrl('sindresorhus.com:123', {\n\tremoveExplicitPort: true\n});\n//=\u003e 'http://sindresorhus.com'\n```\n\n##### sortQueryParameters\n\nType: `boolean`\\\nDefault: `true`\n\nSorts the query parameters alphabetically by key.\n\n```js\nnormalizeUrl('www.sindresorhus.com?b=two\u0026a=one\u0026c=three', {\n\tsortQueryParameters: false\n});\n//=\u003e 'http://sindresorhus.com/?b=two\u0026a=one\u0026c=three'\n```\n\n## Related\n\n- [compare-urls](https://github.com/sindresorhus/compare-urls) - Compare URLs by first normalizing them\n","funding_links":["https://github.com/sponsors/sindresorhus","https://opencollective.com/sindresorhus","https://sindresorhus.com/donate"],"categories":["url","JavaScript","Packages","包","Repository","GIT 仓库","目录","URL","Number"],"sub_categories":["Text","URL","其他"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsindresorhus%2Fnormalize-url","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsindresorhus%2Fnormalize-url","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsindresorhus%2Fnormalize-url/lists"}