SPA will not call my api running on localhost when executed via the android emulator

I am working on doing a simple proof of concept to see if we can leverage capacitor. I have a bare-bones react SPA (used with Visual Studio’s React SPA template basically). I run locally at localhost:5001. It has an endpoint that does a fetch to localhost:5001/api/weather.

The SPA runs fine in browser and loads the data from my server no problem.

When I run in the android emulator, it will not load. I think that I have it configured correctly with the following capacitor.config.ts file:

import { CapacitorConfig } from ‘@capacitor/cli’;

const config: CapacitorConfig = {

appId: ‘com.concept.of.proof’,

appName: ‘CapacitorProofOfConcept’,

webDir: ‘build’,

bundledWebRuntime: true,








export default config;

I am finding the capacitor documentation extremely unhelpful. I would think that configuring to make an actual api call from the native app is a common enough need that there would be some clear instructions on how to get started on that point. A SPA without data is a pretty useless proposition, yet the information on that critical point is very vague. Perhaps it doesn’t feel that way to someone who is more versed in native development, but nobody on my team has ever worked with Android or IOS. I would definitely prefer that the docs that get you started running the app in an emulator include a section about data integration as that seems like a basic necessity for the vast majority of SPAs out there.

Just out of curiosity: how do you “run” your api endpoint on the browser? U have http server next to it? (Which Id say is unlikely given the same port)

I believe you may expect things solved in different ways outside of Capacitor’s scope

If u want to bundle data with the web code, then this is a react thing. In angular you need to bundle the data by putting in an assets folder and use http to fetch it. I reckon react has its ways about this common scenario

If u want to reach data outside the app, use an external endpoint

If you want to use a path in an url to allow users to deeplink: use reacts router features

And in the extremely unlikely event you really want to address a separate web services on the same machine/phone, running different code and having its own http server, then using capacitors (nor cordova’s) http server on localhist is not an option. That one is only to serve the web assets generated by react and copied into the container

Not sure then this is an issue of poor documentation

the web app is running in my browser at https://localhost:5001. The react has something like

const data = await weatherService.getForecast(zipCode);

weatherservice is an async method that uses javascript’s fetch something like (pseudocode, but gives the idea).

let response = fetch(api/forecast/${zipCode})
let data = await response.json();
return data;

I can’t find documentation that helps me know how I can make a fetch to any kind of api, and fetching from an api seems like a pretty basic need for SPA apps. The pattern where you serve a spa that requests data from the same server that served it is such a common approach, that I would have hoped to see some documentation helping guide a developer through understanding what needs to be done.

I immediately was aware that it wouldn’t know how to resolve something like fetch(“api/forecast/90210”) when I was trying to set up a proof of concept. I haven’t found anything anywhere that helps me understand how I would solve that need.

Tell more about the api endpoint. Is it static data? Where does it get data from? What code is behind the endpoint?

In this proof of concept, I am not doing anything significant. I need to just verify that I can make a capacitor spa communicate with an api. I will then need to solve including single sign on tokens either in a cookie or in the headers (cookie would be preferred). SSO integration is not in the scope of my proof of concept, but I am not feeling very confident that there will be much help available.

We have multiple existing SPAs that we want to use capacitor with. In each case, the end points are getting very specific dynamic data for students and teachers. It could be the students in a specific class, the attendance marks for a given day or week, a student’s reading assignments etc.

Our ecosystem is comprised of web-facing APIs that target specific SPA UI needs, and those APIs share a common set of APIs that manage the business rules that apply across all applications.


The fetch interface in a spa in a capacitor container allows you to address APIs easily.

I have no example api for you to test against - but things like the spotify api?

One thing for sure: localhost as url isnt a good idea

Are you getting any type of error in the console/dev tools? You can access the Android Emulator Dev Tools by going to this url in Chrome - chrome://inspect/#devices.

It also isn’t recommended to override the server configuration. It is much better to stick with the standard/default which are as follows:

  • capacitor://localhost - iOS
  • http://localhost - Android

Note that if your API has a CORs configuration, the above hosts need to be added to your CORs configuration in your API/backend.

It is 100% possible to call an external API with your Capacitor app and it is done just like you would in any other web app using fetch or axios or any other library for making HTTP calls. As @Tommertom mentioned, it is a little odd that your API and SPA have the same host and port.

1 Like

I wasn’t aware of the chrome developer tools to see more info, I will see what I can find there.

Having the server with your API also serve out an index.html makes it so your spa doesn’t have to deal with CORS issues in browser, which is really nice. It is also a very simple implementation, simplifying our single sign on with our organization’s identity provider. It also keeps our SPA simple because it fetches relative to wherever it is hosted, so we don’t have to change our API url for our test, or stage lanes. Whether it’s highly unusual or not doesn’t change our reasons for it being built that way.

localhost:5001 is just where the SPA is running when developers run locally. Our SPA doesn’t know, doesn’t care though. It just does the fetch to “api/weather/90210”. During local development that is localhost:5001/api/weather/90210. When we deploy to test and create a capacitor build for test it would fetch to something like Then some day we would conceivably release a capacitor app that works against a prod lane at something like That works beautifully and simply for our SPA in browser and all of our fetch calls are relative, meaning they don’t need code nor configuration for each deployed lane.

If we have to rewrite and rearchitect how our SPA talks to an API in order to use capacitor, that is a pretty big downside for our apps. I wouldn’t expect our approach to a SPA to be that uncommon. As a dev who lives in web-app world, I know very little about Android Studio or Xcode, and am not finding much in the replies that gives me any ideas what I can do to meet our need.

Can you confirm localhost:5001/api/weather/90210 then is just a fake API endpoint within your SPA that returns static content? If that is the case, you also shouldn’t have any problems making HTTP calls to it. I did the exact same thing while developing my Ionic/Capacitor app before the real API was created. I had static json files within my public directory that I used axios to fetch.

Let’s start with looking at the dev tools to see if there are any errors there.

This might help your issue, CORS on device (build version) - #4 by allestaire
Also if you are using vue, you can add devServer on vue.config.json

Maybe you should hire a ionic developer. Seems you’re having an issue with something simple as communicating with a WEB API.

To me that sounds pretty harsh and impolite. You seem to be stuck as concrete in your ideas of how the world looks like

Some introspection and experimentation on your assumptions imho seems like the only way to progress. And sharing the code used in order to provide meaningful feedback.

Or indeed conclude this is not your game and migrate away from web.


people have replied back and gave you some ideas. Seems like you want the answers given to you instead of you working your way thru it.

If you had no idea of using chrome dev tools to debug your issue, then this leads us to believe you have no clue what you are doing. Seems you lack experience in web development world and need some learning.

Hey all, let’s keep it civil and remember that this forum is for helping developers.

My 2¢ on your issue, localhost refers to the local device. For web dev, this refers to your computer. However, when running an application via an Android emulator (or a physical device), localhost now refers to the Android device.

I have a hunch that you’re running this service on your computer on localhost:5001 and your android emulator isn’t able to read from the same localhost since it’s technically a separate device. You might be able to use as your capacitor server so that it reads from your localhost api.

It’s an odd issue that I always have to lookup every so often. This stackoverflow topic has more details on this issue: Accessing localhost:port from Android emulator - Stack Overflow