{"id":13581354,"url":"https://github.com/remusao/tldts","last_synced_at":"2026-02-01T01:20:20.948Z","repository":{"id":24849160,"uuid":"97631656","full_name":"remusao/tldts","owner":"remusao","description":"JavaScript Library to extract domains, subdomains and public suffixes from complex URIs.","archived":false,"fork":false,"pushed_at":"2026-01-28T04:02:58.000Z","size":10547,"stargazers_count":712,"open_issues_count":24,"forks_count":23,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-28T23:33:23.246Z","etag":null,"topics":["domain","javascript","public-suffix-list","tld","typescript","uri","url","url-parsing"],"latest_commit_sha":null,"homepage":"https://npmjs.com/tldts","language":"TypeScript","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/remusao.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-07-18T18:37:24.000Z","updated_at":"2026-01-28T21:55:32.000Z","dependencies_parsed_at":"2023-01-16T22:15:30.890Z","dependency_job_id":"a3fdc89a-feb8-44dc-812e-5bc5c646a50c","html_url":"https://github.com/remusao/tldts","commit_stats":{"total_commits":2666,"total_committers":25,"mean_commits":106.64,"dds":0.6309077269317329,"last_synced_commit":"48648c55c24201039aa742328275841957e5531f"},"previous_names":[],"tags_count":380,"template":false,"template_full_name":null,"purl":"pkg:github/remusao/tldts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remusao%2Ftldts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remusao%2Ftldts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remusao%2Ftldts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remusao%2Ftldts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/remusao","download_url":"https://codeload.github.com/remusao/tldts/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remusao%2Ftldts/sbom","scorecard":{"id":592972,"data":{"date":"2025-08-11","repo":{"name":"github.com/remusao/tldts","commit":"47fc37095cdb3f42e68741c9a429bb6b1c8510d1"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.2,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"12 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/psl.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Warn: no topLevel permission defined: .github/workflows/tests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/psl.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/remusao/tldts/psl.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/psl.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/remusao/tldts/psl.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/psl.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/remusao/tldts/psl.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/remusao/tldts/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/remusao/tldts/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/remusao/tldts/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/remusao/tldts/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/remusao/tldts/tests.yml/master?enable=pin","Warn: npmCommand not pinned by hash: comparison/install.sh:3","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":4,"reason":"6 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-h5c3-5r3r-rr8q","Warn: Project is vulnerable to: GHSA-rmvr-2pp2-xj38","Warn: Project is vulnerable to: GHSA-xx4v-prfh-6cgc","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T22:25:41.940Z","repository_id":24849160,"created_at":"2025-08-20T22:25:41.940Z","updated_at":"2025-08-20T22:25:41.940Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28963584,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T00:42:38.011Z","status":"ssl_error","status_checked_at":"2026-02-01T00:42:35.920Z","response_time":128,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["domain","javascript","public-suffix-list","tld","typescript","uri","url","url-parsing"],"created_at":"2024-08-01T15:02:00.693Z","updated_at":"2026-02-01T01:20:20.932Z","avatar_url":"https://github.com/remusao.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# tldts - Blazing Fast URL Parsing\n\n`tldts` is a JavaScript library to extract hostnames, domains, public suffixes, top-level domains and subdomains from URLs.\n\n**Features**:\n\n1. Tuned for **performance** (order of 0.1 to 1 μs per input)\n2. Handles both URLs and hostnames\n3. Full Unicode/IDNA support\n4. Support parsing email addresses\n5. Detect IPv4 and IPv6 addresses\n6. Continuously updated version of the public suffix list\n7. **TypeScript**, ships with `umd`, `esm`, `cjs` bundles and _type definitions_\n8. Small bundles and small memory footprint\n9. Battle tested: full test coverage and production use\n\n⚠️ If you are migrating to `tldts` from another library like `psl`, make sure to check [the migration section](#migrating-from-other-libraries).\n\n# Install\n\n```bash\nnpm install --save tldts\n```\n\n# Usage\n\nUsing the command-line interface:\n\n```js\n$ npx tldts 'http://www.writethedocs.org/conf/eu/2017/'\n{\n  \"domain\": \"writethedocs.org\",\n  \"domainWithoutSuffix\": \"writethedocs\",\n  \"hostname\": \"www.writethedocs.org\",\n  \"isIcann\": true,\n  \"isIp\": false,\n  \"isPrivate\": false,\n  \"publicSuffix\": \"org\",\n  \"subdomain\": \"www\"\n}\n```\n\nOr from the command-line in batch:\n\n```js\n$ echo \"http://www.writethedocs.org/\\nhttps://example.com\" | npx tldts\n{\n  \"domain\": \"writethedocs.org\",\n  \"domainWithoutSuffix\": \"writethedocs\",\n  \"hostname\": \"www.writethedocs.org\",\n  \"isIcann\": true,\n  \"isIp\": false,\n  \"isPrivate\": false,\n  \"publicSuffix\": \"org\",\n  \"subdomain\": \"www\"\n}\n{\n  \"domain\": \"example.com\",\n  \"domainWithoutSuffix\": \"example\",\n  \"hostname\": \"example.com\",\n  \"isIcann\": true,\n  \"isIp\": false,\n  \"isPrivate\": false,\n  \"publicSuffix\": \"com\",\n  \"subdomain\": \"\"\n}\n```\n\nProgrammatically:\n\n```js\nconst { parse } = require('tldts');\n\n// Retrieving hostname related informations of a given URL\nparse('http://www.writethedocs.org/conf/eu/2017/');\n// { domain: 'writethedocs.org',\n//   domainWithoutSuffix: 'writethedocs',\n//   hostname: 'www.writethedocs.org',\n//   isIcann: true,\n//   isIp: false,\n//   isPrivate: false,\n//   publicSuffix: 'org',\n//   subdomain: 'www' }\n```\n\nModern _ES6 modules import_ is also supported:\n\n```js\nimport { parse } from 'tldts';\n```\n\nAlternatively, you can try it _directly in your browser_ here: https://npm.runkit.com/tldts\n\nCheck [README.md](/packages/tldts/README.md) for more details about the API.\n\n# Migrating from other libraries\n\nTL;DR—here is a quick overview of how to use `tldts` to match the default behavior of the `psl` library. Skip to after the tables for a more detailed explanation.\n\n| | Parsing a hostname |\n| --- | --- |\n| `tldts` | `tldts.parse('spark-public.s3.amazonaws.com', { allowPrivateDomains: true })` |\n| `psl` | `psl.parse('spark-public.s3.amazonaws.com')` |\n| Note | Make sure to include `{ allowPrivateDomains: true }` to consider private suffixes |\n\n| | Parsing a URL |\n| --- | --- |\n| `tldts` | `tldts.parse('https://spark-public.s3.amazonaws.com/data', { allowPrivateDomains: true })` |\n| `psl` | `psl.parse(new URL('https://spark-public.s3.amazonaws.com/data').hostname)` |\n| Note | No need to extract hostnames from URLs, `tldts` can do that for you |\n\n| | Getting the domain |\n| --- | --- |\n| `tldts` | `tldts.getDomain('spark-public.s3.amazonaws.com', { allowPrivateDomains: true })` |\n| `psl` | `psl.get('spark-public.s3.amazonaws.com')` |\n| Note | Using specific functions like `getDomain` are more efficient then relying on `parse` |\n\n| | Getting the Public Suffix |\n| --- | --- |\n| `tldts` | `tldts.getPublicSuffix('spark-public.s3.amazonaws.com', { allowPrivateDomains: true })` |\n| `psl` | `psl.parse('spark-public.s3.amazonaws.com').tld` |\n\n\n*Explanation*. There are multiple libraries which can be used to parse URIs\nbased on the Public Suffix List. Not all these libraries offer the same\nbehavior by default and depending on your particular use-case, this can matter.\nWhen migrating from another library to `tldts`, make sure to read this section\nto preserve the same behavior.\n\nThe biggest difference between `tldts`'s default behavior and some other\nlibraries like `psl` has to do with which suffixes are considered by default.\nThe default for `tldts` is to **only consider the ICANN section** and ignore the\nPrivate section.\n\nConsider this example using the unmaintained `psl` library:\n```js\nconst psl = require('psl');\n\npsl.parse('https://spark-public.s3.amazonaws.com/dataanalysis/loansData.csv')\n// {\n//   input: 'spark-public.s3.amazonaws.com',\n//   tld: 's3.amazonaws.com', \u003c\u003c\u003c Public Suffix is from Private section\n//   sld: 'spark-public',\n//   domain: 'spark-public.s3.amazonaws.com',\n//   subdomain: null,\n//   listed: true\n// }\n```\n\nAnd now with `tldts`:\n```js\nconst { parse } = require('tldts');\n\nparse('spark-public.s3.amazonaws.com');\n// {\n//   domain: 'amazonaws.com',\n//   domainWithoutSuffix: 'amazonaws',\n//   hostname: 'spark-public.s3.amazonaws.com',\n//   isIcann: true,\n//   isIp: false,\n//   isPrivate: false,\n//   publicSuffix: 'com', \u003c\u003c\u003c By default, use Public Suffix from ICANN section\n//   subdomain: 'spark-public.s3'\n// }\n```\n\nTo get the **same behavior**, you need to pass the `{ allowPrivateDomains: true }` option:\n```js\nconst { parse } = require('tldts');\n\nparse('spark-public.s3.amazonaws.com', { allowPrivateDomains: true });\n// {\n//   domain: 'spark-public.s3.amazonaws.com',\n//   domainWithoutSuffix: 'spark-public',\n//   hostname: 'spark-public.s3.amazonaws.com',\n//   isIcann: false,\n//   isIp: false,\n//   isPrivate: true,\n//   publicSuffix: 's3.amazonaws.com', \u003c\u003c\u003c Private Public Suffix is used\n//   subdomain: ''\n// }\n```\n\nHere are some other differences which can make your life easy. `tldts` **accepts\nboth hostnames and URLs as arguments**, so you do not need to parse your\ninputs before handing them over to `tldts`:\n\n```js\nconst { parse } = require('tldts');\n\n// Both are fine!\nparse('spark-public.s3.amazonaws.com', { allowPrivateDomains: true });\nparse('https://spark-public.s3.amazonaws.com/dataanalysis/loansData.csv', { allowPrivateDomains: true });\n```\n\n`tldts` offers dedicated methods to extract the Public Suffix, domain,\nsubdomain, etc. without having to rely on the more generic `parse` function.\nThis is also *more efficient* than calling `parse`, because less work as to be\ndone.\n\n```js\nconst {\n  getHostname,\n  getDomain,\n  getPublicSuffix,\n  getSubdomain,\n  getDomainWithoutSuffix,\n} = require('tldts');\n\nconst url = 'https://spark-public.s3.amazonaws.com';\n\nconsole.log(getHostname(url)); // spark-public.s3.amazonaws.com\nconsole.log(getDomain(url, { allowPrivateDomains: true })); // spark-public.s3.amazonaws.com\nconsole.log(getPublicSuffix(url, { allowPrivateDomains: true })); // s3.amazonaws.com\nconsole.log(getSubdomain(url, { allowPrivateDomains: true })); // ''\nconsole.log(getDomainWithoutSuffix(url, { allowPrivateDomains: true })); // spark-public\n```\n\n## Contributors\n\n`tldts` is based upon the excellent `tld.js` library and would not exist without\nthe [many contributors](https://github.com/remusao/tldts/graphs/contributors) who worked on the project.\n\nThis project would not be possible without the amazing Mozilla's\n[public suffix list][] either. Thank you for your hard work!\n\n# License\n\n[MIT License](LICENSE).\n\n[badge-ci]: https://secure.travis-ci.org/remusao/tldts.svg?branch=master\n[badge-downloads]: https://img.shields.io/npm/dm/tldts.svg\n[public suffix list]: https://publicsuffix.org/list/\n[list the recent changes]: https://github.com/publicsuffix/list/commits/master\n[changes Atom Feed]: https://github.com/publicsuffix/list/commits/master.atom\n[public suffix]: https://publicsuffix.org/learn/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremusao%2Ftldts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fremusao%2Ftldts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremusao%2Ftldts/lists"}