{"id":15413435,"url":"https://github.com/wooorm/dead-or-alive","last_synced_at":"2025-10-30T11:53:55.162Z","repository":{"id":204717782,"uuid":"712495176","full_name":"wooorm/dead-or-alive","owner":"wooorm","description":"check if urls are dead or alive","archived":false,"fork":false,"pushed_at":"2024-10-08T15:20:19.000Z","size":87,"stargazers_count":50,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-29T17:11:33.245Z","etag":null,"topics":["404","alive","check","dead","link","normalize","url"],"latest_commit_sha":null,"homepage":"","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/wooorm.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":"funding.yml","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},"funding":{"github":"wooorm"}},"created_at":"2023-10-31T15:25:07.000Z","updated_at":"2025-03-05T15:27:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"0a30baa9-0817-41cf-a87d-901294450446","html_url":"https://github.com/wooorm/dead-or-alive","commit_stats":{"total_commits":24,"total_committers":2,"mean_commits":12.0,"dds":0.04166666666666663,"last_synced_commit":"057704b01dc422f584eed2bb8294bae8cab40a09"},"previous_names":["wooorm/dead-or-alive"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wooorm%2Fdead-or-alive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wooorm%2Fdead-or-alive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wooorm%2Fdead-or-alive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wooorm%2Fdead-or-alive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wooorm","download_url":"https://codeload.github.com/wooorm/dead-or-alive/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247378142,"owners_count":20929296,"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":["404","alive","check","dead","link","normalize","url"],"created_at":"2024-10-01T16:57:04.201Z","updated_at":"2025-10-30T11:53:50.108Z","avatar_url":"https://github.com/wooorm.png","language":"JavaScript","funding_links":["https://github.com/sponsors/wooorm"],"categories":["JavaScript"],"sub_categories":[],"readme":"# dead-or-alive\n\n[![Build][badge-build-image]][badge-build-url]\n[![Coverage][badge-coverage-image]][badge-coverage-url]\n[![Downloads][badge-downloads-image]][badge-downloads-url]\n[![Size][badge-size-image]][badge-size-url]\n\nCheck if urls are dead or alive.\n\n## Contents\n\n* [What is this?](#what-is-this)\n* [When should I use this?](#when-should-i-use-this)\n* [Install](#install)\n* [Use](#use)\n* [API](#api)\n  * [`deadOrAlive(href[, options])`](#deadoralivehref-options)\n  * [`defaultAnchorAllowlist`](#defaultanchorallowlist)\n  * [`defaultSleep(retries)`](#defaultsleepretries)\n  * [`AnchorAllow`](#anchorallow)\n  * [`Options`](#options)\n  * [`Result`](#result)\n  * [`Sleep`](#sleep)\n* [Errors](#errors)\n  * [`dead`](#dead)\n  * [`fetch`](#fetch)\n  * [`lost-hash-with-meta-http-equiv`](#lost-hash-with-meta-http-equiv)\n  * [`lost-hash-with-non-html`](#lost-hash-with-non-html)\n  * [`lost-hash-with-redirect`](#lost-hash-with-redirect)\n  * [`max-redirect`](#max-redirect)\n  * [`missing-anchor`](#missing-anchor)\n  * [`shared-declarative-refresh`](#shared-declarative-refresh)\n* [Compatibility](#compatibility)\n* [Security](#security)\n* [Contribute](#contribute)\n* [License](#license)\n\n## What is this?\n\nThe main goal of this project is to make sure URLs in docs are okay.\nAs in,\n“if I link to it and a user goes there,\nwill it work,\nand will they be there or somewhere else?”\nIt uses modern JavaScript that works everywhere,\nand it uses the DOM when available,\nso you can use it in browsers, Node.js, workers.\n\nIt is made to be used by other tools.\nSuch as a markdown tool,\n[`remark-lint-no-dead-urls`][github-remark-lint-no-dead-urls].\n\n* [x] works in browser, node, worker, etc\n* [x] checks if anchors (such as `#readme`) point to elements\n* [x] follows HTTP and HTML redirects\n* [x] supports DOM clobber prefix (`user-content-`)\n* [x] emits warnings\n\n## When should I use this?\n\nYou can use this when you want to build a link checker.\n\nIf you want to support SPAs or other client-side JS,\nthis doesn’t do that.\n\n## Install\n\nThis package is [ESM only][github-gist-esm].\nIn Node.js (version 18+),\ninstall with [npm][npm-install]:\n\n```sh\nnpm install dead-or-alive\n```\n\nIn Deno with [`esm.sh`][esm-sh]:\n\n```js\nimport {deadOrAlive} from 'https://esm.sh/dead-or-alive@1'\n```\n\nIn browsers with [`esm.sh`][esm-sh]:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import {deadOrAlive} from 'https://esm.sh/dead-or-alive@1?bundle'\n\u003c/script\u003e\n```\n\n## Use\n\n```js\nimport {deadOrAlive} from 'dead-or-alive'\n\nconsole.log(await deadOrAlive('https://something-that-is-dead.com'))\nconsole.log(await deadOrAlive('https://github.com'))\n```\n\n…yields:\n\n```txt\n{\n  messages: [\n    [1:1: Unexpected error fetching `https://something-that-is-dead.com/`] { … }\n  ],\n  status: 'dead',\n  url: undefined,\n  urls: undefined\n}\n{\n  messages: [],\n  status: 'alive',\n  url: 'https://github.com/',\n  urls: Set(203) {\n    'https://github.githubassets.com/',\n    'https://avatars.githubusercontent.com/',\n    …\n  }\n}\n```\n\n## API\n\nThis package exports the identifiers\n[`deadOrAlive`][api-dead-or-alive],\n[`defaultAnchorAllowlist`][api-default-anchor-allowlist],\nand [`defaultSleep`][api-default-sleep].\nIt exports the TypeScript types\n[`AnchorAllow`][api-anchor-allow],\n[`Options`][api-options],\n[`Result`][api-result],\nand [`Sleep`][api-sleep].\nThere is no default export.\n\n### `deadOrAlive(href[, options])`\n\nCheck if a url is dead or alive.\n\n###### Parameters\n\n* `href` (`URL` or `string`)\n  — URL\n* `options` ([`Options`][api-options], optional)\n  — configuration\n\n###### Returns\n\nResult ([`Promise\u003cResult\u003e`][api-result]).\n\n###### Notes\n\nTo improve performance,\ndecrease `maxRetries` and/or decrease the value used\nfor `sleep`.\nThe normal behavior is to assume connections might be flakey and to sleep a\nwhile and retry a couple times.\n\nIf you do not care about HTML redirects,\nwhether anchors work,\nand what further URLs are used on,\nyou can pass `checkAnchor: false`,\n`findUrls: false`,\nand `followMetaHttpEquiv: false`,\nwhich enables a fast path without parsing HTML.\n\n### `defaultAnchorAllowlist`\n\nAllow certain anchors ([`Array\u003cAnchorAllow\u003e`][api-anchor-allow]).\n\nThis currently allows text fragments everywhere.\n\n### `defaultSleep(retries)`\n\nCalculate milliseconds to sleep between tries.\n\nThe function is defined as `x ** 3 * 1000`,\nso the first sleep is `1 ** 3 * 1000` is 1s,\n2nd is 8s,\n3rd is 27s,\netc.\n\n###### Parameters\n\n* `retries` (`number`)\n  — try\n\n###### Returns\n\nMilliseconds to sleep (`number`).\n\n### `AnchorAllow`\n\nAllow extra anchors (TypeScript type).\n\nThe first item is a regular expression to match URLs (origin and path,\nso without search or hash),\nand the second item is a regular expression to match hashes (without `#`).\nWhen both match,\nthe hash is allowed.\n\n###### Type\n\n```ts\nexport type AnchorAllow = [url: RegExp, anchor: RegExp]\n```\n\n### `Options`\n\nConfiguration (TypeScript type).\n\n###### Fields\n\n* `anchorAllowlist` ([`Array\u003cAnchorAllow\u003e`][api-anchor-allow], default: `true`)\n  — allow anchors;\n  each tuple is checked to match URLs (origin and path,\n  so without search or hash),\n  and then to match hashes (without `#`);\n  when both match,\n  the hash is allowed,\n  and no `missing-anchor` error is used\n* `checkAnchor` (`boolean`, default: `true`)\n  — check whether URL hashes point to elements\n* `followMetaHttpEquiv` (`boolean`, default: `true`)\n  — follow HTML redirects;\n  a `\u003cmeta content=0;to http-equiv=refresh\u003e` can be useful for static sites\n  such as those on GH pages\n* `findUrls` (`boolean`, default: `true`)\n  — find URLs in the final resource;\n  currently applies to HTML\n* `maxRedirects` (`number`, default: `5`)\n  — inclusive maximum redirects to follow\n* `maxRetries` (`number`, default: `1`)\n  — inclusive maximum number to try again on failures\n* `resolveClobberPrefix` (`boolean`, default: `true`)\n  — accept `user-content-` prefix in `id` on elements\n* `sleep` ([`Sleep`][api-sleep], default: [`defaultSleep`][api-default-sleep])\n  — calculate milliseconds to sleep between tries\n* `timeout` (`number`, default: `3000`)\n  — timeout for HTTP request in milliseconds\n* `userAgent` (`string`, default: `'Mozilla/5.0 … Safari/537.36'`,\n  a modern Chrome on macOS user agent)\n  — user agent\n\n### `Result`\n\nResult (TypeScript type).\n\n###### Fields\n\n* `messages` ([`Array\u003cVFileMessage\u003e`][github-vfile-message])\n  — messages where the first is a fatal error when dead\n* `permanent` (`boolean` or `undefined`)\n  — whether all redirects were permanent\n* `status` (`'alive'` or `'dead'`)\n  — status\n* `url` (`string` or `undefined`)\n  — final URL if alive\n* `urls` (`Set\u003cstring\u003e` or `undefined`)\n  — further URLs if `findUrls: true` and the resource was HTML\n\n### `Sleep`\n\nCalculate milliseconds to sleep between tries (TypeScript type).\n\n###### Parameters\n\n* `retries` (`number`)\n  — try\n\n###### Returns\n\nMilliseconds to sleep (`number`).\n\n## Errors\n\n### `dead`\n\n```txt\nUnexpected not ok response `$status` (`$statusText`) on `$url`\n```\n\nThis error is used when a URL looks temporarily or permenantly dead.\n\n### `fetch`\n\n```txt\nUnexpected error fetching `$url`\n```\n\nThis error is used when for some unknown reason the URL is dead.\nIt might be that you are offline,\nor the URL is temporarily dead,\nor something else is wrong.\nBut it looks dead.\n\n### `lost-hash-with-meta-http-equiv`\n\n```txt\nUnexpected hash in URL `$url` that redirects with `meta[http-equiv=refresh]` to `$url` losing the hash, remove the hash from the original URL\n```\n\nThis warning is used when a URL with an anchor gets an HTML redirect,\nwhich looses that anchor.\nYou can remove the hash from the original URL.\nOr find a similar section on the final URL.\n\n### `lost-hash-with-non-html`\n\n```txt\nUnexpected hash in URL `$url` to non-html ($contentType) losing the hash, remove the hash from the original URL\n```\n\nThis warning is used when a URL with an anchor resolves to some non-HTML thing,\nwhich might be an error.\nPerhaps you can remove the hash from the original URL?\n\n### `lost-hash-with-redirect`\n\n```txt\nUnexpected hash in URL `$url` that redirects to `$url` losing the hash, remove the hash from the original URL\n```\n\nThis warning is used when a URL with an anchor gets an HTTP redirect,\nwhich looses that anchor.\nYou can remove the hash from the original URL.\nOr find a similar section on the final URL.\n\n### `max-redirect`\n\n```txt\nUnexpected redirect to `$url`, too many redirects\n```\n\nThis error is used when there are more redirects than\n`options.maxRedirects`.\nIncrease this number or use your browser to see if the URL ends up redirecting\nto something that works.\n\n### `missing-anchor`\n\n```txt\nUnexpected missing anchor element on `$url` for fragment `$fragment`, remove if unneeded or refer to an existing element\n```\n\nThis error is used when a hash is used in a URL but no such element can be\nfound.\nElements can match hashes by their `id` or by their `name` (when `\u003ca\u003e`).\nThe prefix `user-content-` is ignored on elements as that’s what GitHub and\n[`rehype-sanitize`][github-rehype-sanitize] use to solve DOM clobbering.\n\nRemove the hash if unneeded or refer to a different,\nexisting element.\n\n### `shared-declarative-refresh`\n\n```txt\nUnexpected invalid URL `$url` in `content` on `meta[http-equiv=refresh] relative to `$url`\n```\n\nThis error is used when an HTML redirect such as\n`\u003cmeta content=0;xxx http-equiv=refresh\u003e` is used,\nbut `xxx` does not parse as a URL.\nUse your browser to see if the URL ends up redirecting to something that works.\n\n## Compatibility\n\nThis projects is compatible with maintained versions of Node.js.\n\nWhen we cut a new major release,\nwe drop support for unmaintained versions of Node.\nThis means we try to keep the current release line,\n`dead-or-alive@1`,\ncompatible with Node.js 18.\n\n## Security\n\nThis package is safe.\n\n## Contribute\n\nYes please!\nSee [How to Contribute to Open Source][open-source-guide-contribute].\n\n## License\n\n[MIT][file-license] © [Titus Wormer][wooorm]\n\n\u003c!-- Definitions --\u003e\n\n[api-anchor-allow]: #anchorallow\n\n[api-dead-or-alive]: #deadoralivehref-options\n\n[api-default-anchor-allowlist]: #defaultanchorallowlist\n\n[api-default-sleep]: #defaultsleepretries\n\n[api-options]: #options\n\n[api-result]: #result\n\n[api-sleep]: #sleep\n\n[badge-build-image]: https://github.com/wooorm/dead-or-alive/workflows/main/badge.svg\n\n[badge-build-url]: https://github.com/wooorm/dead-or-alive/actions\n\n[badge-coverage-image]: https://img.shields.io/codecov/c/github/wooorm/dead-or-alive.svg\n\n[badge-coverage-url]: https://codecov.io/github/wooorm/dead-or-alive\n\n[badge-downloads-image]: https://img.shields.io/npm/dm/dead-or-alive.svg\n\n[badge-downloads-url]: https://www.npmjs.com/package/dead-or-alive\n\n[badge-size-image]: https://img.shields.io/bundlejs/size/dead-or-alive\n\n[badge-size-url]: https://bundlejs.com/?q=dead-or-alive\n\n[npm-install]: https://docs.npmjs.com/cli/install\n\n[esm-sh]: https://esm.sh\n\n[file-license]: license\n\n[github-gist-esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n\n[github-rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize\n\n[github-remark-lint-no-dead-urls]: https://github.com/remarkjs/remark-lint-no-dead-urls\n\n[github-vfile-message]: https://github.com/vfile/vfile-message\n\n[open-source-guide-contribute]: https://opensource.guide/how-to-contribute/\n\n[wooorm]: https://wooorm.com\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwooorm%2Fdead-or-alive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwooorm%2Fdead-or-alive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwooorm%2Fdead-or-alive/lists"}