# How to manually test a web API

A few weeks ago, I showed the [basic ideas and terminology of web APIs](https://how-to.dev/what-you-should-know-about-web-apis). In this article, I will demonstrate how to apply this knowledge, and try an API with some manual testing.

## Tweak query

The easy way to start testing any API is to find an example that works—and then tweak it. You can pick any website and see what requests it does. For example, when you open developer tools in Chrome and reload my blog at [how-to.dev](https://how-to.dev/what-is-an-api), you can see plenty of requests sent by the website:


![Image description](https://cdn.hashnode.com/res/hashnode/image/upload/v1692166774002/18dcd0e4-2935-4a5b-b1f7-167c2ff68d42.png)

In the list, we have a few types or requests:
* _script_ or _stylesheet_ with names 4421.a65a… or 6238.6ee7…,
* _fetch_ with names such as user, tags, events, 
* _xhr_ with name event,
* and some other types with resources: _svg_, _avif_, _font_.

We are the most interested in _fetch_ and _xhr_ request types. Both could be triggered from the JavaScript side and used for talking to the web API. The other requests we can see here are requests to load some static files—the code or some media content. For each of the queries we see on the list, we can copy one of the formats:



![Image description](https://cdn.hashnode.com/res/hashnode/image/upload/v1692166776490/24335d2f-1d97-448f-9920-b363dbcc654b.png)

Copying the code allows you to easily do one of two things:
* rerun the query exactly as it was done by the application, or
* tweak the query to see how the API works with different input.

### Fetch

Fetch is a JavaScript interface to communicate with servers—for example, to talk to a web API. You can read more at [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). Here we will see our example query:

```JS
fetch("https://how-to.dev/api/user", {
  "headers": {
    "accept": "application/json",
    "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
    "baggage": "sentry-environment=vercel-production,sentry-release=736267205a61e0548a85c08aab089d3f1421126b,sentry-transaction=%2F%5B...slug%5D,sentry-public_key=0fbf92e944b8468cb9706e15c488c84e,sentry-trace_id=a2a1dbab6f5b4c619173000812050469,sentry-sample_rate=0",
    "content-type": "application/json",
    "if-none-match": "\"as45c9ut8od\"",
    "sec-ch-ua": "\"Not/A)Brand\";v=\"99\", \"Google Chrome\";v=\"115\", \"Chromium\";v=\"115\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"macOS\"",
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-origin",
    "sentry-trace": "a2a1dbab6f5b4c619173000812050469-8d225d0201152147-0"
  },
  "referrer": "https://how-to.dev/what-is-an-api",
  "referrerPolicy": "origin-when-cross-origin",
  "body": null,
  "method": "GET",
  "mode": "cors",
  "credentials": "include"
});
```

As you can see, there are a lot of details. To run the query, paste this code in the console in dev tools and add `.then(console.log)` at the end of it. The fetch function returns a promise, and adding `console.log` as a callback will show us the output right there on the screen.



![Image description](https://cdn.hashnode.com/res/hashnode/image/upload/v1692166778904/31c7bc47-f77b-4316-8e82-45871a008918.png)

You can modify any of the parameters provided to the call, and in this way you can see how the API will behave.

The big advantage of this approach is that you will reuse the credential information already available in your browser. If you have an open session, there will be a cookie in your browser, and it will be sent with your request: in this way, the server will know you are you, and where you should be given access.

## GET request

Another option to test the API is to put the URL where you want to send your GET request into the address bar. By default, the browser does the GET request to the endpoint and displays  the response on the screen. It will not always work as expected: in some rare cases, the API can be flexible enough to support different formats depending on the query headers. In such a case, it may be that address bar requests show HTML, whereas the API call gets JSON.

### Demo API

[Httpbin](http://httpbin.org/) is an example API we can use for our testing. Its main page is some documentation that shows all the endpoints available for us:


![Image description](https://cdn.hashnode.com/res/hashnode/image/upload/v1692166780902/28341166-ccac-405f-8fc0-da89155c551b.png)

Let’s try visiting some of the endpoints directly from the browser.

### Address bar

When you open one of the endpoints [http://httpbin.org/uuid](http://httpbin.org/uuid) you will get a response similar to this:


![Image description](https://cdn.hashnode.com/res/hashnode/image/upload/v1692166782842/a3f9aeb5-8993-4913-82e3-c560e27e6ae9.png)

You can see more details by opening the dev tools and the network tab. When you refresh the page, you can see all the headers that were sent and received by the browser:


![Image description](https://cdn.hashnode.com/res/hashnode/image/upload/v1692166784846/0d00fd37-369d-4808-9bf4-1249ce464bdc.png)

You can use this approach to test GET requests to web APIs.

## POST request

Creating a POST from scratch is more complicated. You could try writing `fetch` calls, but as you saw earlier in this article, they can be quite complicated. Let’s use an API testing tool instead.

### Hoppscotch

[Hoppscotch](https://hoppscotch.io/) is an API development tool that we can use to send any type of request—POST included. If you’ve heard about Postman, this is an open-source alternative. For the testing, I’ll send a POST request with some JSON data to Httpbin’s POST endpoint. At the initial screen, I set the URL to `http://httpbin.org/post`, the method to _POST_. In the _Body_ tab, I set the _Content Type_ to `application/json` and the _Raw Request Body_ to:

```JSON
{"test": 123}
```

Here’s the request just before sending:

![Image description](https://cdn.hashnode.com/res/hashnode/image/upload/v1692166786839/c9e6742f-074d-459c-8ed6-00a1460a688d.png)

The initial attempt fails because we are accessing an external server. There are few options to address it, with _Proxy_ being the easiest to get you off the ground:


![Image description](https://cdn.hashnode.com/res/hashnode/image/upload/v1692166788654/a0029f50-98f1-4335-a953-0ead223ba347.png)

The result after retrying the request:


![Image description](https://cdn.hashnode.com/res/hashnode/image/upload/v1692166790547/93ffd231-4a3b-43d8-9384-d49e0a157ae6.png)

As you can see, the Httpbin API just returns a bunch  of technical information about the request and the body. 

This simple test skips the issue of authorization—many POST requests are only available to the user that is logged in on the server and fail for anonymous users. Covering this concept fully is a topic for another article.

## Want to learn more?

If you are interested in learning more about API or related topics, you can sign up for occasional emails from [my newsletter](https://how-to-dev.ck.page/a5c69742db). 
