238

When I create a brand new project using react-native init (RN version 0.29.1) and put a fetch in the render method to the public facebook demo movie API, it throws a Network Request Failed. There is a very useless stack trace and I can't debug network requests in the chrome console. Here is the fetch I'm sending:

fetch('http://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => {
        return responseJson.movies;
      })
      .catch((error) => {
        console.error(error);
      });
11
  • 1
    I'm not sure. I'm using the iOS simulator and I thought it used my computer's internet connection
    – Alek Hurst
    Commented Jul 17, 2016 at 8:00
  • 8
    http -> https (if possible) will most likely fix your issue
    – Nick Zuber
    Commented Oct 12, 2016 at 0:20
  • 2
    I was using the ip 192.168.1.25:3000 from ifconfig without binding my server to that ip rails server --binging=192.168.1.25 --port=3000 Commented Mar 21, 2019 at 16:03
  • 2
    None of these answers allow you to catch the error. Commented Oct 17, 2019 at 22:39
  • 3
    Yes I tried all. Nothing worked for me Commented Apr 27, 2020 at 4:31

42 Answers 42

191

The problem here is that iOS does not allow HTTP requests by default, only HTTPS. If you want to enable HTTP requests add this to your info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
16
  • 2
    This answer worked for me. For others new to React Native, this file (info.plist) can also be edited through xcode: stackoverflow.com/a/38219454/1299792
    – Marklar
    Commented Feb 28, 2017 at 22:26
  • 143
    what about android? I am facing same issue in android as well. Commented May 19, 2017 at 9:45
  • 34
    Exactly. Anyone have the answer for android?
    – Zach Cook
    Commented Aug 31, 2017 at 6:15
  • 3
    I have given INTERNET permission in the AndroidManifest.xml but yet I am having this issue. Any idea how to fix it? I would have torn all my hairs if I had any..grrr
    – masud_moni
    Commented Apr 25, 2018 at 6:15
  • 2
    what about android ? Im facing this issue right now Commented May 14, 2018 at 4:42
76

I was using localhost for the address, which was obviously wrong. After replacing it with the IP address of the server (in the network that emulator is), it worked perfectly.

Edit

In Android Emulator, the address of the development machine is 10.0.2.2. More explanation here

For Genymotion, the address is 10.0.3.2. More info here

4
  • 5
    Thank you. Probably the only response I've seen that works for android. Used my networks IP address and it works. eg http://<Network IP emulator connects to>:<port where API is served>/api/tasks Commented Jul 19, 2018 at 7:35
  • 3
    Don't forget the "http://" or else it won't work ... was wondering why it would work on postman but not with fetch
    – Moumou
    Commented Jul 31, 2018 at 20:48
  • @Mahmoodvcs Your answer help me a lot of, thank you so much, I am using android emulator. Commented Aug 30, 2019 at 0:03
  • Yes this works. Change from localhost to the actual IP address of your development computer. Commented Aug 28, 2021 at 20:33
67

Not recommended to allow all domains for http. Make an exception for just the necessary domains.

Source: Configuring App Transport Security Exceptions in iOS 9 and OSX 10.11

Add the following to the info.plist file of your app:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow HTTP requests-->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>
4
  • 55
    what about android?
    – arisalexis
    Commented Nov 2, 2016 at 11:42
  • 4
    There seems to be multiple info.plist files in multiple directories in my React Native app. Any idea which folder contains the correct file to change?
    – Marklar
    Commented Feb 28, 2017 at 6:27
  • 2
    @Marklar [your_project_folder_name]/ios/[your_project_folder_name]/Info.plist
    – Stich
    Commented Apr 5, 2017 at 12:09
  • if I use my localhost here: <key>yourserver.com</key>, when ready I'm ready to publish, I'll need to change it, correct? Commented May 23, 2020 at 6:33
43

I got the same issue on Android 9 because of the "http" and issue resolved by just adding android:usesCleartextTraffic="true" in AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
  android:usesCleartextTraffic="true"
 .......>
 .......
</application>

1
  • 4
    Thanks, this worked for me as well. It happens because Android is not supporting HTTP anymore per default on API 28.
    – Gui Herzog
    Commented Dec 1, 2019 at 18:57
25

For us it was because we were uploading a file and the RN filePicker did not give the proper mime type. It just gave us 'image' as the type. We needed to change it to 'image/jpg' to get the fetch to work.

form.append(uploadFileName, {
  uri : localImage.full,
  type: 'image/jpeg',
  name: uploadFileName
 })
1
  • @JohhanSantana You could probably look at the raw image data and get it from the beginning, but the react native picker just came back 'image' for me.
    – NickJ
    Commented Jan 15, 2019 at 2:06
18

if you using localhost just change it :

from :http://localhost:3030 to :http://10.0.2.2:3030

4
  • How do you change it from localhost to your IP address?
    – Olumide
    Commented Mar 19, 2021 at 6:13
  • @Olumide just change your url . And thanks this worked Commented Mar 30, 2021 at 21:44
  • I changed it from http://localhost:3000 to http://192.168.1.256:3000 and it worked
    – Sudarshan
    Commented Aug 18, 2022 at 13:21
  • http://10.0.2.2:3030 works! But why?
    – Yairopro
    Commented Dec 26, 2023 at 19:34
17

I got the same issue on Android but I managed to find a solution for it. Android is blocking cleartext traffic (non-https-requests) since API Level 28 by default. However, react-native adds a network-security-config to the debug version (android/app/src/debug/res/xml/react_native_config.xml) which defines some domains (localhost, and the host IPs for AVD / Genymotion), which can be used without SSL in dev mode. You can add your domain there to allow http requests.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="false">localhost</domain>
    <domain includeSubdomains="false">10.0.2.2</domain>
    <domain includeSubdomains="false">10.0.3.2</domain>
    <domain includeSubdomains="true">dev.local</domain>
  </domain-config>
</network-security-config>
2
  • This worked for me with react native 0.59 and target sdk 28 :) Commented Jul 31, 2019 at 7:23
  • that would be nice if I even had res/xml/... path... should I add, will it make a difference? using RN - 0.72 , sdk > 30
    – BoxaBole
    Commented Nov 30, 2023 at 8:20
16

For Android user:

  1. Replace localhosts to a Lan IP addresses because when you run the project on an Android device, localhost is pointing to the Android device, instead of your computer, example: change http://localost to http://192.168.1.123

  2. If your request URL is HTTPS and your Android device is under a proxy, assume you have installed User-added CA(like burp suite's CA or Charles's CA) in your Android device, make sure your Android version is below Nougat(7.0), because: Changes to Trusted Certificate Authorities in Android Nougat

    User-added CAs
    Protection of all application data is a key goal of the Android application sandbox. Android Nougat changes how applications interact with user- and admin-supplied CAs. By default, apps that target API level 24 will—by design—not honor such CAs unless the app explicitly opts in. This safe-by-default setting reduces application attack surface and encourages consistent handling of network and file-based application data.

12

React Native Docs gives the answer for this.

Apple has blocked implicit cleartext HTTP resource loading. So we need to add the following our project's Info.plist (or equivalent) file.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

React Native Docs -> Integration With Existing Apps -> Test your integration -> Add App Transport Security exception

1
  • It changed nothing :/
    – BoxaBole
    Commented Nov 30, 2023 at 8:27
11

The problem may be in server configuration.

Android 7.0 has a bug described here. Workaround proposed by Vicky Chijwani:

Configure your server to use the elliptic curve prime256v1. For example, in Nginx 1.10 you do this by setting ssl_ecdh_curve prime256v1;

11

I was having this problem for Android-

URL- localhost/authToken.json - didn't work :(

URL- 10.106.105.103/authToken.json - didn't work :(

URL- http://10.106.105.103/authToken.json - worked :) :D

Note- Use ifconfig on Linux or ipconfig on Windows to find machine IpAddress

0
6

I came across the same issue on Android Emulator, where I tried to access an external HTTPS URL with a valid certificate. But fetching that URL in react-native failed

'fetch error:', { [TypeError: Network request failed]
sourceURL: 'http://10.0.2.2:8081/index.delta?platform=android&dev=true&minify=false' }

1) To find out the exact error in the logs, I first enabled 'Debug JS Remotely' using Cmd + M on the app

2) The error reported was

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

3) I added the URL's valid certificate using this method -> STEP 2

http://lpains.net/articles/2018/install-root-ca-in-android/

This certificate gets added to the User tab.

4) Add the attribute android:networkSecurityConfig attribute to AndroidManifest.xml

Add a Network Security Configuration file res/xml/network_security_config.xml:

<network-security-config>
    <base-config>
        <trust-anchors>
            <certificates src="user"/>
            <certificates src="system"/>
        </trust-anchors>
    </base-config>
</network-security-config>

This should work and give you an expected response.

1
  • I just needed to do step 4 in order to work. Thanks! Commented Oct 9, 2019 at 2:47
5

For Android, you may have missed to add permission in AndroidManifest.xml Need to add the following permission.

<uses-permission android:name="android.permission.INTERNET" /> 
4
  • 1
    I already do have that even though I am getting that error, is there any other workaround?
    – masud_moni
    Commented Apr 22, 2018 at 5:30
  • @masud_moni you find way to fix the problem? im still having the same problem Commented Oct 30, 2019 at 12:56
  • @RafaelRotiroti yes i solved that issue, but although it is been a while, it is hard to remember, if you have used the permission and still facing issues, please share details. I will try my best to help, and you will have others also to look into it
    – masud_moni
    Commented Oct 30, 2019 at 20:31
  • @masud_moni thank you, i've fixed that problem using the ip given after run ifconfig command. AVD creates an virtual device, so using the same theory than virtual machines that is nothing hosted in 127.0.0.1 in my device. So i use 192.168.x.x IP and everything works fine as well Commented Oct 31, 2019 at 14:42
5

I have similar problem. In my case requests to localhost was working and suddenly stopped. It turn out that the problem was that I was turn off my wifi on my android phone.

4

in my case i have https url but fetch return Network Request Failed error so i just stringify the body and it s working fun

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue'
  })
});

3

By running the mock-server on 0.0.0.0
Note: This works on Expo when you are running another server using json-server.


Another approach is to run the mock server on 0.0.0.0 instead of localhost or 127.0.0.1.

This makes the mock server accessible on the LAN and because Expo requires the development machine and the mobile running the Expo app to be on the same network the mock server becomes accessible too.

This can be achieved with the following command when using json-server

json-server --host 0.0.0.0 --port 8000 ./db.json --watch

Visit this link for more information.

3

Just add

<uses-permission android:name="android.permission.INTERNET" />

    <application
      android:usesCleartextTraffic="true"

in your AndroidManifest.xml and then replace fetch URL domain (localhost) with your IP address,

const dataRaw = await fetch('http://192.168.8.102:4000');
1
  • replacing with ip worked.
    – CrackerKSR
    Commented Feb 17, 2022 at 7:44
2

This worked for me, android uses a special type of IP address 10.0.2.2 then port number

import { Platform } from 'react-native';

export const baseUrl = Platform.OS === 'android' ?
    'http://10.0.2.2:3000/'
: 
'http://localhost:3000/';
1
  • Sad that this is the only one that worked for me
    – aletede91
    Commented Apr 26, 2021 at 15:17
2

if you use docker for the REST api, a working case for me was to replace hostname: http://demo.test/api with the machine ip address: http://x.x.x.x/api . You can get the IP from checking what ipv4 you have on your wireless network. You should have also the wifi from phone on.

2

You should handle the error case in .then for fetch API.

For example:

fetch(authURl,{ method: 'GET'})
.then((response) => {      
  const statusCode = response.status;
  console.warn('status Code',statusCode);
  if(statusCode==200){
    //success code
  }else{
    //handle other error code
  }      
},(err) => {
  console.warn('error',err)
})
.catch((error) => {
  console.error(error);
  return error;
});
2

For me ... I have https already ... and the issue went away once I added 'Content-type': 'application/json' to headers

headers: {
  Authorization: token,
  'Content-type': 'application/json',
  /** rest of headers... */
}

Platform: Android

1

This is not an answer but option. I switched to https://github.com/joltup/rn-fetch-blob It works good both for form-data and files

1

HTTP is not allowed anymore. Pleas use HTTPS

Starting with Android API 28 and iOS 9, these platforms disable insecure HTTP connections by default.

1

It my case, it was showing same for https requests as well.

Reinstalling the application solved it.

1

Had the same issue with React-native Expo and Node Express back-end. The problem is about a conflict between an emulator localhost and server localhost. Your back-end-server might be ruunning on 127.0.0.1:8000, but an emulator can't find this.

In terminal find your Ipv4-Address with a command 'ipconfig'. For ex., it will be 192.138.1.40

After this put it into your fetch ( 'http://192.138.1.40:8080/'). And what is also important - run your back-end-server with the same host and port. On Node Express for example:

app.listen(8080, () => console.log("Server is running!"))

1
  • Thank you. Your answer worked for me with using express as the backend and an expo application on a real android device. Commented Apr 27, 2023 at 15:44
1

In my case i just change https to http and the problem was resolved (Using android studio).

0

The solution is simple update nodejs version 14 or higher

2
  • why this fixes the issue? Commented Nov 10, 2021 at 4:32
  • because invalid connection over tls in my case Commented Nov 11, 2021 at 1:06
0

"dependencies": {"react": "17.0.2","react-native": "0.66.1"}, I faced this problem with the Android emulator.

  1. Add these lines of code inside AndroidManifest.xml

     <application
      ....
      ....
     android:usesCleartextTraffic="true">
    
  2. Then, try to run your code in a real physical device, instead of emulator,
    to run on physical devices - connect your usb and try to run npx react-native run-android

0

fixed TypeError: Network request failed when upload file to http not https with Android debug builds

In react-native 0.63.2 (I'm testing) or some higher version, if just use fetch to upload file to a http (not https) server, will meet TypeError: Network request failed.

Here I use axios@0.27.2 as client running on an Android phone successfully upload a file to react-native-file-server as server running on another Android phone.

client need edit JAVA and JS code, server no need edit JAVA code.

With debug builds, must commenting out line number 43 in this file android/app/src/debug/java/com/YOUR_PACKAGE_NAME/ReactNativeFlipper.java

38      NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
39      NetworkingModule.setCustomClientBuilder(
40          new NetworkingModule.CustomClientBuilder() {
41            @Override
42            public void apply(OkHttpClient.Builder builder) {
43      //        builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
44            }
45          });
46      client.addPlugin(networkFlipperPlugin);

Maybe also need add android:usesCleartextTraffic="true" under <application of android/app/src/main/AndroidManifest.xml , on my test, it's not necessary on both debug and release builds.

  onFileSelected = async (file) => {
    // API ref to the server side BE code `addWebServerFilter("/api/uploadtodir", new WebServerFilter()`
    // https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/android/src/main/java/webserver/WebServer.java#L356
    // could not be 'localhost' but IP address
    const serverUploadApi = 'http://192.168.1.123:8080/api/uploadtodir';

    // the folder on server where file will be uploaded to, could be e.g. '/storage/emulated/0/Download'
    const serverFolder = '/storage/emulated/0/FileServerUpload';

    const fileToUpload = {
      // if want to upload and rename, it can be `name: 'foo.bar'`, but can not be 'foo'
      // only if your server upload code support file name without type, on our server
      // https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/android/src/main/java/webserver/WebServer.java#L372
      // will cause java.lang.StringIndexOutOfBoundsException in substring()
      name: file.name,

      // type is necessary in Android, it can be 'image/jpeg' or 'foo/bar', but can not be
      // 'foo', 'foo/', '/foo' or undefined, otherwise will cause `[AxiosError: Network Error]`
      type: 'a/b',

      uri: Platform.OS === 'android' ? file.uri : file.uri.replace('file://', ''),
    };

    const form = new FormData();
    form.append('path', serverFolder);
    form.append('uploadfile', fileToUpload);

    // ref to the server side FE code `this.axios.post("/api/uploadtodir", parms, config)`
    // https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/fileserverwebdoc/src/views/Manage.vue#L411
    let res = await axios.post(serverUploadApi, form, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      onUploadProgress: function (progressEvent) {
        console.warn(progressEvent);
      },
    });

    // ref to the server side BE code `return newFixedLengthResponse("Suss");`
    // https://github.com/flyskywhy/react-native-file-server/blob/1034a33dd6d8b0999705927ad78368ca1a639add/android/src/main/java/webserver/WebServer.java#L380
    if (res.data === 'Suss') {
      console.warn('Upload Successful');
    } else if (res.data === 'fail') {
      console.warn('Upload Failed');
    }
  };
0

If you are connecting to a HTTPS website please check the internet connection of your emulator. (In my case, I'm using a connected phone emulator via USB and it's internet was offline)

Not the answer you're looking for? Browse other questions tagged or ask your own question.