For Node with `Promise` support, a simple Node shim for (part of the) [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) requires only a smattering of extra code compared to other answers:

```js
const fs = require(`fs`);
const http = require(`http`);
const https = require(`https`);

module.exports = function fetch(url) {
 return new Promise((resolve, reject) => {
 const data = [];
 const client = url.startsWith("https") ? https : http;
 client
 .request(url, (res) => {
 res.on(`data`, (chunk) => data.push(chunk));
 res.on(`end`, () => {
 const asBytes = Buffer.concat(data);
 const asString = asBytes.toString(`utf8`);
 resolve({
 arrayBuffer: async () => asBytes,
 json: async () => JSON.parse(asString),
 text: async () => asString,
 });
 });
 res.on(`error`, (e) => reject(e));
 })
 .end();
 });
};
```

Which you can then use to whatever you need using normal fetch syntax:

```js
const fetch = require(`./tiny-fetch.js`);

fetch(`https://placekitten.com/200/300`)
 .then(res => res.arrayBuffer())
 .then(bytes => fs.writeFileSync(`kitten.jpg`, bytes))
 .catch(e => console.error(e));

fetch(`https://jsonplaceholder.typicode.com/todos/1`)
 .then(res => res.json())
 .then(obj => console.log(obj))
 .catch(e => console.error(e));

// etc.
```