546

I have this error when I compile my code in node.js, how can I fix it?

RefernceError: fetch is not defined

enter image description here

This is the function I am doing, it is responsible for recovering information from a specific movie database.

function getMovieTitles(substr){  
  pageNumber=1;
  let url = 'https://jsonmock.hackerrank.com/api/movies/search/?Title=' + substr + "&page=" + pageNumber;
  fetch(url).then((resp) => resp.json()).then(function(data) {
    let movies = data.data;
    let totPages = data.total_pages;
    let sortArray = [];
    for(let i=0; i<movies.length;i++){
        sortArray.push(data.data[i].Title);
     }
    for(let i=2; i<=totPages; i++){
           let newPage = i;
           let url1 = 'https://jsonmock.hackerrank.com/api/movies/search/?Title=' + substr + "&page=" + newPage;

          fetch(url1).then(function(response) {
              var contentType = response.headers.get("content-type");
              if(contentType && contentType.indexOf("application/json") !== -1) {
                return response.json().then(function(json) {
                  //console.log(json); //uncomment this console.log to see the JSON data.

                 for(let i=0; i<json.data.length;i++){
                    sortArray.push(json.data[i].Title);
                 }

                 if(i==totPages)console.log(sortArray.sort());

                });
              } else {
                console.log("Oops, we haven't got JSON!");
              }
            });

        }
  })
  .catch(function(error) {
    console.log(error);
  });   
}
xaif
  • 553
  • 6
  • 27
jasa1704
  • 5,579
  • 3
  • 9
  • 6
  • 5
    Welcome to SO, please provide the details on what have you tried so far? Please provide a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) wherever required. Also please take the time to read [How to Ask](https://stackoverflow.com/questions/how-to-ask) – Pratibha Jan 25 '18 at 00:24
  • 9
    `fetch` is not a standard nodejs method - you need `node-fetch` – Jaromanda X Jan 25 '18 at 00:27
  • 6
    `fetch()` was designed for the browser and then back-ported to node.js in a third party module whcih you are apparently missing. The `request()` or `request-promise()` library is more natively built for node.js and supports a much wider range of options for node.js including streams, a zillion authentication methods, etc... – jfriend00 Jan 25 '18 at 00:41
  • 1
    Please, don’t include an image of your error. See: https://meta.stackoverflow.com/questions/285551/why-should-i-not-upload-images-of-code-data-errors – Étienne Miret Jun 07 '23 at 10:51

26 Answers26

807

If you're using a version of Node prior to 18, the fetch API is not implemented out-of-the-box and you'll need to use an external module for that, like node-fetch.

Install it in your Node application like this

npm install node-fetch

then put the line below at the top of the files where you are using the fetch API:

import fetch from "node-fetch";

If your application cannot be updated to use ESM (aka import syntax), and you need to use CommonJS (aka require), then stick with v2 of node-fetch. As per their README, v2 will continue to receive critical bug fixes.

npm install node-fetch@2

and then this will work,

const fetch = require("node-fetch");
allejo
  • 2,076
  • 4
  • 25
  • 40
Adrian Theodorescu
  • 11,664
  • 2
  • 23
  • 30
94

This is a quick dirty fix, please try to eliminate this usage in production code.

If fetch has to be accessible with a global scope

import fetch from 'node-fetch'
globalThis.fetch = fetch
Endless
  • 34,080
  • 13
  • 108
  • 131
XY L
  • 25,431
  • 14
  • 84
  • 143
  • 2
    This was the only way that I was able to get WebStorm to recognize the promise returned by `fetch` and autocomplete the available methods. Agreed that it should be avoided in production, but very helpful for local dev! – FoxMulder900 Oct 07 '18 at 19:21
  • 1
    @FoxMulder900 This is how you could have still IntelliSense without having it global defined: `const nodeFetch = require('node-fetch') as typeof fetch;` – Stefan Rein Aug 30 '21 at 02:04
  • globalThis is not defined – Oleg Abrazhaev Mar 15 '23 at 16:53
51

You can use cross-fetch from @lquixada

Platform agnostic: browsers, node or react native

Install

npm install --save cross-fetch

Usage

With promises:

import fetch from 'cross-fetch';
// Or just: import 'cross-fetch/polyfill';

fetch('//api.github.com/users/lquixada')
  .then(res => {
    if (res.status >= 400) {
      throw new Error("Bad response from server");
    }
    return res.json();
  })
  .then(user => {
    console.log(user);
  })
  .catch(err => {
    console.error(err);
  });

With async/await:

import fetch from 'cross-fetch';
// Or just: import 'cross-fetch/polyfill';

(async () => {
  try {
    const res = await fetch('//api.github.com/users/lquixada');

    if (res.status >= 400) {
      throw new Error("Bad response from server");
    }

    const user = await res.json();

    console.log(user);
  } catch (err) {
    console.error(err);
  }
})();
Richard Vergis
  • 1,037
  • 10
  • 20
  • This helped for metaweather api, well explained in github documentation. Thanks for Sharing – krupesh Anadkat Dec 22 '18 at 08:08
  • 1
    Using crossfetch's polyfill also worked for me using typescript and node and receiving the `ReferenceError: fetch is not defined` error from `amazon-cognito-identity-js`. – John Hamelink May 22 '19 at 09:52
42

If you want to avoid npm install and not running in browser, you can also use nodejs https module;

const https = require('https')
const url = "https://jsonmock.hackerrank.com/api/movies";
https.get(url, res => {
  let data = '';
  res.on('data', chunk => {
    data += chunk;
  });
  res.on('end', () => {
    data = JSON.parse(data);
    console.log(data);
  })
}).on('error', err => {
  console.log(err.message);
})

UPDATE APRIL 2023

Starting node version 18 and 19, Fetch API is available (Experimental, Not recommended for production use until stable) https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#fetch

Here are some examples (tested: v18.15.0/v19.9.0):

// Promise version:

const url = "https://jsonmock.hackerrank.com/api/movies";

fetch(url).then(res => {
    return res.json();
}).then(data => {
    console.log('DATA: ', data);
})

OR

// async/await version

const url = "https://jsonmock.hackerrank.com/api/movies";

const getData = async () => {
    const response = await fetch(url);

    if (response.ok) {
        const data = await response.json();

        console.log('DATA: ', data);
    }
};
getData();
Khuram Niaz
  • 881
  • 10
  • 16
  • 2
    Just remember to add `.end()` right at the bottom of this snippet to actually start the request off. See [docs](https://nodejs.org/api/http.html#http_request_end_data_encoding_callback) – Fred Truter Mar 02 '21 at 20:48
21

fetch came to Node v17 under experimental flag --experimental-fetch

It will be available in Node v18 without the flag.

https://github.com/nodejs/node/pull/41749#issue-1118239565

You no longer need any additional package to be installed

krl
  • 5,087
  • 4
  • 36
  • 53
LearningToCode
  • 249
  • 2
  • 15
  • 6
    Node 18 is out, and it is still experimental. – SamGoody May 03 '22 at 21:07
  • 2
    I use node v 18 in my local env and `fetch` just works on the server. On Netlify with v18 however it does not work. I need node-fetch. – Timo Aug 11 '22 at 20:02
15

Node.js hasn't implemented the fetch() method, but you can use one of the external modules of this fantastic execution environment for JavaScript.

In one of the other answers, "node-fetch" is cited and that's a good choice.

In your project folder (the directory where you have the .js scripts) install that module with the command:

npm i node-fetch --save

Then use it as a constant in the script you want to execute with Node.js, something like this:

const fetch = require("node-fetch");
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Miguel Murillo
  • 175
  • 1
  • 3
15

EDITED - New Solution

To use the latest version (3.0.0) you must do the import like this:

const fetch = (url) => import('node-fetch').then(({default: fetch}) => fetch(url));


Old Anwser:

This may not be the best solution, but if you install this version :

npm install node-fetch@1.7.3

you can now use the line below without error's.

const fetch = require("node-fetch");
Rafael Lourenço
  • 213
  • 4
  • 10
  • Is there a specific reason to use this older version instead of using the latest one, especially noting [this vulnerability](https://snyk.io/test/npm/node-fetch/1.7.3) with it? – LW001 Sep 03 '21 at 12:18
  • @LW001 When I had this problem this was a quick fix I did. If you use the new version(3.0.0) , it will get an error in import and then you'll get another one that says "fetch is not a function". As you said, this version has vulnerabilities and you should always use the latest one, so I edited my answer to solve the problem. – Rafael Lourenço Oct 14 '21 at 14:04
  • 1
    In your code (new one) the Promise will not work. If you need to use `require` go with version 2 which will get critical updates: "If you cannot switch to ESM, please use v2 which remains compatible with CommonJS. Critical bug fixes will continue to be published for v2." `node-fetch@2` – Mika Feb 17 '22 at 16:14
11

You should add this import in your file:

import * as fetch from 'node-fetch';

And then, run this code to add the node-fetch:
$ yarn add node-fetch

If you're working with typescript, then install node-fetch types:
$ yarn add @types/node-fetch

ofir_aghai
  • 3,017
  • 1
  • 37
  • 43
  • 4
    If I import in this way and use typescript, I have this error `TS2349: This expression is not callable. Type 'typeof import("/node_modules/@types/node-fetch/index")' has no call signatures.`. It works only with `require`. – Oleg Abrazhaev Jul 13 '21 at 08:17
  • run `$ yarn add @types/node-fetch` to installing node-fetch types – ofir_aghai Jul 13 '21 at 12:47
  • of course I did, it is about using es6 `import` vs `require`. seems like `node-fetch` does not support this modern import syntaxis. – Oleg Abrazhaev Jul 14 '21 at 14:31
6

You have to use the isomorphic-fetch module to your Node project because Node does not contain Fetch API yet. For fixing this problem run below command:

npm install --save isomorphic-fetch es6-promise

After installation use below code in your project:

import "isomorphic-fetch"
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
AmerllicA
  • 29,059
  • 15
  • 130
  • 154
  • 11
    Not actively maintained; has been years since the last accepted PR. https://github.com/matthew-andrews/isomorphic-fetch/graphs/contributors – tomByrer Mar 10 '19 at 15:22
  • FYI, this can lead to difficult in typescript projects because this library does not provide proper types. An easier router is to use cross-fetch which is very similar but plays nice with typescript. For a react app where you are assuming that normal fetch will be available in the browser you can make this a dev dependency and use `import 'cross-fetch/polyfill';` in test setup to smooth the rough edges of the testing environment. – Chris Wininger Feb 04 '21 at 14:39
6

For those also using typescript on node-js and are getting a ReferenceError: fetch is not defined error

npm install these packages:

    "node-fetch": "^2.3.0"

Then include:

import Global = NodeJS.Global;
export interface GlobalWithCognitoFix extends Global {
    fetch: any
}
declare const global: GlobalWithCognitoFix;
global.fetch = require('node-fetch');
CWSites
  • 1,428
  • 1
  • 19
  • 34
closedloop
  • 651
  • 8
  • 10
  • 49
    `amazon-cognito-identity-js` is not relevant to this question and not needed to install to solve this error. It is also not related to typescript. – cnvzmxcvmcx Jul 10 '19 at 17:15
  • 1
    Hi! So i am having exactly the same issue, but this still din't fix anything, do you have any other work around? – Masnad Nihit Oct 24 '19 at 20:25
  • I'm also looking for a work-around. Doing import fetch from 'node-fetch'; instead is one fix for typescript – JohnFlux Aug 15 '20 at 03:49
5

Best one is Axios library for fetching. use npm i --save axios for installng and use it like fetch, just write axios instead of fetch and then get response in then().

Mohammad Quanit
  • 120
  • 2
  • 14
5

It seems fetch support URL scheme with "http" or "https" for CORS request.

Install node fetch library npm install node-fetch, read the file and parse to json.

const fs = require('fs')
const readJson = filename => {
  return new Promise((resolve, reject) => {
    if (filename.toLowerCase().endsWith(".json")) {
      fs.readFile(filename, (err, data) => {
        if (err) {
          reject(err)
          return
        }
        resolve(JSON.parse(data))
      })
    }
    else {
      reject(new Error("Invalid filetype, <*.json> required."))
      return
    }
  })
}

// usage
const filename = "../data.json"
readJson(filename).then(data => console.log(data)).catch(err => console.log(err.message))
5

In HackerRank, some libraries are installed by default and some are not.

Because it is running Node.js, the fetch API is not installed by default.

The best thing for you to do is to check whether the libraries are or not installed.

on the top of the exercise, there is the following:

const https = require('https');

Please try to add this to the top as well:

const axios = require('axios');

and then run the code.

If there is a compilation error, then it's not available, otherwise you can use axios, which is a good alternative to fetch

To use it with then, you can:

function getMovieTitles(substr){
  axios.get(url)
    .then(function(response){
      console.log(response.data);
    })
}

or taking advantage of the async/await

async function getMovieTitles(substr){
  let response = await axios.get(url)
  console.log(response.data);
}
nabais
  • 1,981
  • 1
  • 12
  • 18
5

In node.js you can use : node-fetch package

npm i node-fetch

then :

import fetch from 'node-fetch';

here is a full sample in (nodejs) :

import fetch from "node-fetch";

const fetchData = async () => {
  const res = await fetch("https://restcountries.eu/rest/v2/alpha/col"); // fetch() returns a promise, so we need to wait for it

  const country = await res.json(); // res is now only an HTTP response, so we need to call res.json()

  console.log(country); // Columbia's data will be logged to the dev console
};

fetchData();
Endless
  • 34,080
  • 13
  • 108
  • 131
3

This is the related github issue This bug is related to the 2.0.0 version, you can solve it by simply upgrading to version 2.1.0. You can run npm i graphql-request@2.1.0-next.1

asma
  • 599
  • 1
  • 7
  • 19
2

The following works for me in Node.js 12.x:

npm i node-fetch;

to initialize the Dropbox instance:

var Dropbox = require("dropbox").Dropbox;
var dbx = new Dropbox({
   accessToken: <your access token>,
   fetch: require("node-fetch")    
});

to e.g. upload a content (an asynchronous method used in this case):

await dbx.filesUpload({
  contents: <your content>,
  path: <file path>
});
2

This worked for me:

const nodeFetch = require('node-fetch') as typeof fetch;
Radim Šafrán
  • 463
  • 7
  • 16
2

I encountered this error when I deployed my docker instance to production. It was weird to see the application failed with the error in this question.

I realised the Dockerfile had FROM node:16.13.1 and my system node version was 20.3.1.

If you don't want to use 'node-fetch' as shown in many answers and use 'fetch' ensure that you're using node version 18 or above. The reference error is likely because your node version is less than 18.

Mahendra Liya
  • 12,912
  • 14
  • 88
  • 114
1

For me these are looking more simple.

npm install node-fetch
import fetch from "node-fetch";
0

There are actually a lot of different libraries for making fetch available in the browser.

The main ones I'm aware of are:

I currently use node-fetch, and it has worked fine, but I don't really know which one is "the best". (though the openbase.com pages I linked to provide some metadata on usage [eg. Github stars, npm downloads], which can help)

Venryx
  • 15,624
  • 10
  • 70
  • 96
0
npm i node-fetch 

Once installed, in your JavaScript file:

import fetch from "node-fetch";

Lastly make this change package.json file:

"type": "module"
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
0

I got this error in a Jest test when using native fetch in Node.js version 18(.15.0).

Upgrading to the latest version of Jest (in my case from 27.5.1 to 29.5.0) fixed the issue:

npm install jest@latest
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
-1

Solution without installations

enter image description here

Method 1

import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

constructor(@Inject(PLATFORM_ID) private platformId: Object) { 
    // constructor code
}

ngOnInit() {
    if (isPlatformBrowser(this.platformId)) {
        // Client only code. Any javascript base functions
    }
    if (isPlatformServer(this.platformId)) {
        // Server only code. Any javascript base functions
    }
}

Method 2

import {  PLATFORM_ID} from '@angular/core';
    import { isPlatformBrowser } from '@angular/common';
    
    @Component({
      selector: 'app-navigation',
      templateUrl: './navigation.component.html',
      styleUrls: ['./navigation.component.scss'],
      changeDetection: ChangeDetectionStrategy.OnPush,
    })
    export class NavigationComponent implements OnInit {
      private isBrowser: boolean = false;
    
      constructor(
        @Inject(PLATFORM_ID) private platformId: Object
      ) {
        this.isBrowser = isPlatformBrowser(platformId);
      }
    
      ngOnInit(): void {
          if (this.isBrowser) {
            fetch('https://jsonplaceholder.typicode.com/posts/1')
                .then((response) => response.json())
                .then((json) => console.log(json));
            }
        }
      }

DEMO - JSFIDDLE - Open console to view the fetch api service working

Surya R Praveen
  • 3,393
  • 1
  • 24
  • 25
-2

Just make your app.js file Extension as app.mjs and the problem will be solved!!!:)

-3

Might sound silly but I simply called npm i node-fetch --save in the wrong project. Make sure you are in the correct directory.

JFM
  • 57
  • 7
-3

If need install:

npm install --save global-fetch

then

var fetch = require("node-fetch");
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
  • Is it `global-fetch` or `node-fetch`? – Zsolt Meszaros Dec 23 '21 at 22:48
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 23 '21 at 22:49