{"id":16292461,"url":"https://github.com/exogen/node-fetch-har","last_synced_at":"2025-04-23T21:09:39.621Z","repository":{"id":37735036,"uuid":"190935659","full_name":"exogen/node-fetch-har","owner":"exogen","description":"Generate HAR entries for requests made with node-fetch","archived":false,"fork":false,"pushed_at":"2024-04-29T05:10:58.000Z","size":12836,"stargazers_count":31,"open_issues_count":31,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-23T21:09:31.530Z","etag":null,"topics":["fetch","fetch-api","har","har-file","http-requests","node-fetch","ssr"],"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/exogen.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":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"exogen","buy_me_a_coffee":"mosswood"}},"created_at":"2019-06-08T21:14:25.000Z","updated_at":"2024-04-29T05:11:01.000Z","dependencies_parsed_at":"2024-06-18T21:19:42.191Z","dependency_job_id":"311e11c0-9620-4fbd-81c0-eb1aa1a7eb9c","html_url":"https://github.com/exogen/node-fetch-har","commit_stats":{"total_commits":55,"total_committers":2,"mean_commits":27.5,"dds":0.2545454545454545,"last_synced_commit":"e72299c6fceac68c5da3d676a8fb11a66800cebb"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Fnode-fetch-har","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Fnode-fetch-har/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Fnode-fetch-har/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Fnode-fetch-har/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exogen","download_url":"https://codeload.github.com/exogen/node-fetch-har/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250514786,"owners_count":21443209,"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":["fetch","fetch-api","har","har-file","http-requests","node-fetch","ssr"],"created_at":"2024-10-10T20:06:45.811Z","updated_at":"2025-04-23T21:09:39.604Z","avatar_url":"https://github.com/exogen.png","language":"JavaScript","readme":"# node-fetch-har\n\n[![npm](https://img.shields.io/npm/v/node-fetch-har.svg)][npm]\n[![Travis](https://img.shields.io/travis/exogen/node-fetch-har.svg)][travis]\n[![Coveralls](https://img.shields.io/coveralls/github/exogen/node-fetch-har.svg)][coveralls]\n\nA [Fetch API][fetch] wrapper that records [HAR logs][har] for server requests\nmade with [node-fetch][]. You can then expose this data to get visibility into\nwhat’s happening on the server.\n\n**See also the companion project for Next.js integration, [next-fetch-har](https://github.com/exogen/next-fetch-har).**\n\n![Demo](./demo.gif)\n\n## Support\n\nDid this project bring you joy? Want to support updates? Check out\n[my GitHub Sponsors page](https://github.com/sponsors/exogen).\n\nAlternatively…\n\n\u003ca href=\"https://www.buymeacoffee.com/mosswood\" target=\"_blank\"\u003e\u003cimg src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" alt=\"Buy Me A Coffee\" style=\"height: 60px !important;width: 217px !important;\"\u003e\u003c/a\u003e\n\n## Status\n\n**STABLE**\n\nDue to the wide variety seen in HTTP requests, please test thoroughly with your\napplication and [file an issue](https://github.com/exogen/node-fetch-har/issues)\nif you find any problems.\n\n## Warning\n\n⚠️ **HAR files can contain sensitive information like cookies or passwords.**\nSince this library is for capturing what happens on the server, this is\nespecially important because it is information that users can’t normally acces\nin their own browser. Be careful about sharing this data. If you provide a way\nto expose it, ensure it is only enabled for superusers or in secure\nenvironments.\n\n## Usage\n\nThe `withHar` function takes a base Fetch implementation such as `node-fetch`\nand returns a new one that records HAR entries:\n\n```js\nimport { withHar } from \"node-fetch-har\";\nimport nodeFetch from \"node-fetch\";\n\nconst fetch = withHar(nodeFetch);\n```\n\nIndividual HAR entries can then accessed on the `response` object:\n\n```js\nfetch(\"https://httpstat.us/200\").then(response =\u003e {\n  console.log(response.harEntry);\n  return response;\n});\n```\n\nOr by configuring `withHar` with an `onHarEntry` callback:\n\n```js\nconst fetch = withHar(nodeFetch, {\n  onHarEntry: entry =\u003e console.log(entry)\n});\n```\n\nYou can also customize `onHarEntry` for individual requests:\n\n```js\nconst fetch = withHar(nodeFetch);\n\nfetch(\"https://httpstat.us/200\", {\n  onHarEntry: entry =\u003e console.log(entry)\n});\n```\n\nTo disable HAR tracking for individual requests, set the `har` option to `false`:\n\n```js\nfetch(\"https://httpstat.us/200\", { har: false }).then(response =\u003e {\n  console.log(response.harEntry); // Should be undefined.\n  return response;\n});\n```\n\nThe above options will give you individual HAR entries. It’s likely that you’ll\nwant to collect multiple requests into a single HAR log. For example, all API\ncalls made while rendering a single page. Use the `createHarLog` function to\ngenerate a complete HAR object that can hold multiple entries.\n\nYou can pass the resulting object via the `har` option and entries will\nautomatically be added to it:\n\n```js\nimport { withHar, createHarLog } from \"node-fetch-har\";\nimport nodeFetch from \"node-fetch\";\n\nasync function run() {\n  const har = createHarLog();\n  const fetch = withHar(nodeFetch, { har });\n\n  await Promise.all([\n    fetch(\"https://httpstat.us/200\"),\n    fetch(\"https://httpstat.us/200\"),\n    fetch(\"https://httpstat.us/200\")\n  ]);\n\n  console.log(har);\n}\n```\n\nYou can also call `createHarLog` with an array of entries, if you’ve already\ncollected them in a different way:\n\n```js\nconst har = createHarLog(entries);\n```\n\n### …with Isomorphic Fetch\n\nWhen using “universal” libraries like [cross-fetch][], [isomorphic-fetch][], or\n[isomorphic-unfetch][], **make sure you only import this library and wrap the\nFetch instance on the server.** Not only does this library require built-in Node\nmodules, but it’s unnecessary in the browser anyway, since you can already spy\non requests (and export HAR logs) via the Network tab.\n\nThe following example assumes your bundler (e.g. webpack) is configured to strip\nout conditional branches based on `process.browser`.\n\n```js\nimport baseFetch from \"isomorphic-unfetch\";\n\nlet fetch = baseFetch;\n\nif (!process.browser) {\n  const { withHar } = require(\"node-fetch-har\");\n  fetch = withHar(baseFetch);\n}\n```\n\n### Redirects\n\nDue to redirects, it is possible for a single `fetch` call to result in multiple\nHTTP requests. As you might expect, multiple HAR entries will be recorded as\nwell.\n\nWith the Fetch API’s `redirect` option in `follow` mode (the default), calls\nwill transparently follow redirects; that is, you get the response for the\nfinal, redirected request. Likewise, the `harEntry` property of the response\nwill correspond with that final request.\n\nTo get the HAR entries for the redirects, use the `har` or `onHarEntry` options\n(described above). The redirects will be appended to the log and reported with\n`onHarEntry` in addition to the final entry, in the order that they were made.\n\n### Request Body\n\nIf there is no `Content-Type` header specified in the request, then `postData`\nwill not be populated since we would not be able to populate the required\n`mimeType` field.\n\nAdditionally, `params` will only be populated if the `Content-Type` is exactly\n`application/x-www-form-urlencoded`. If it is anything else (including\n`multipart/form-data`) then `text` will be populated instead.\n\nThere may be limited support for exotic request body encodings.\n\n### Custom Agent\n\nThis library works by using the custom `agent` option supported by `node-fetch`.\nHowever, it should still work if you pass your own custom `agent` as well. The\nprovided agent instance will have its `addRequest` method instrumented with the\nnecessary HAR tracking behavior. This behavior will be skipped if the request\ndoes not originate from a Fetch instance returned by `withHar`.\n\n### Page Info\n\nThe second argument to `createHarLog` allows you to add some initial page info:\n\n```js\nconst har = createHarLog([], { title: \"My Page\" });\n```\n\nIf you have additional pages within a single log, you’ll have to add them\nyourself:\n\n```js\nhar.log.pages.push({ title: \"2nd Page\" });\n```\n\nIf not provided, a default page will be created with an ID of `page_1`. By\ndefault, all HAR entries will reference this page. To customize the page that\nentries reference, use the `harPageRef` option to `withHar`:\n\n```js\nconst fetch = withHar(nodeFetch, { har, harPageRef: \"page_2\" });\n```\n\nOr use the `harPageRef` option to `fetch` for individual requests:\n\n```js\nawait fetch(url, { harPageRef: \"page_2\" });\n```\n\n## Examples\n\nSee the [demo](./demo/pages/index.js) for an example of exposing an SSR HAR\nlog from Next.js.\n\nRun the demo like so:\n\n```console\n$ cd demo\n$ yarn\n$ yarn start\n```\n\n## TODO\n\n- More tests for different response types, protocols (HTTP/2), encodings, etc.\n\n## How does it work?\n\n`node-fetch` supports a custom `agent` option. This can be used to capture very\ndetailed information about the request all the way down to the socket level if\ndesired. This library only uses it in a very simplistic way, to capture a few\nkey timestamps and metadata like the HTTP version.\n\n[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\n[node-fetch]: https://github.com/bitinn/node-fetch\n[har]: http://www.softwareishard.com/blog/har-12-spec/\n[cross-fetch]: https://github.com/lquixada/cross-fetch\n[isomorphic-fetch]: https://github.com/matthew-andrews/isomorphic-fetch\n[isomorphic-unfetch]: https://github.com/developit/unfetch\n[npm]: https://www.npmjs.com/package/node-fetch-har\n[travis]: https://travis-ci.org/exogen/node-fetch-har\n[coveralls]: https://coveralls.io/github/exogen/node-fetch-har\n","funding_links":["https://github.com/sponsors/exogen","https://buymeacoffee.com/mosswood","https://www.buymeacoffee.com/mosswood"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexogen%2Fnode-fetch-har","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexogen%2Fnode-fetch-har","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexogen%2Fnode-fetch-har/lists"}