JavaScript 3 min read

Fetch API: Calling APIs From the Browser

The Fetch API is how modern websites load data without reloading the page — live search, chatbots, dashboards and forms. Learn GET and POST requests, error handling, JSON and security basics.

On this page

Key takeaways

  • fetch() is the browser’s built-in way to call APIs and load data without reloading the page.
  • Always check response.ok, handle errors and show loading states.
  • Never put secret API keys in browser code — call third-party APIs from your server instead.

Live search, chat assistants, “load more” buttons, form submissions without page reloads, dashboards that refresh — all use the Fetch API. The chatbot on this site sends your message to a WordPress REST endpoint with fetch, and the server talks to the AI provider so no key is ever exposed. Here’s how it works.

A basic GET request#

async function loadPosts() {
  const res = await fetch('/wp-json/wp/v2/posts?per_page=5');
  if (!res.ok) throw new Error('HTTP ' + res.status);
  const posts = await res.json();
  return posts.map(p => p.title.rendered);
}

fetch returns a Promise. The response doesn’t throw on 404 or 500 errors — you must check res.ok (true for status 200–299).

Sending data with POST#

const res = await fetch('/wp-json/ikp/v1/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ messages: [{ role: 'user', content: 'What is TTFB?' }] })
});
const data = await res.json();

For HTML forms, send new FormData(formElement) as the body and skip the Content-Type header — the browser sets it.

Robust error handling and timeouts#

async function getJSON(url, ms = 10000) {
  const ctrl = new AbortController();
  const t = setTimeout(() => ctrl.abort(), ms);
  try {
    const res = await fetch(url, { signal: ctrl.signal });
    if (!res.ok) throw new Error('Server error ' + res.status);
    return await res.json();
  } finally {
    clearTimeout(t);
  }
}
  • Show a loading indicator and disable the button while waiting.
  • Show a friendly message on failure, with a retry option.
  • Cancel outdated requests (e.g. previous search keystrokes) with AbortController.
  • Debounce input-driven requests (wait ~200–300 ms after typing stops).

Need a hand with this?

Get a quick, honest review of your website’s SEO.

Chat on WhatsApp

Security essentials#

Risk Solution
Exposed API keys Proxy calls through your server (WordPress REST route, serverless function)
Cross-site request forgery Nonces/CSRF tokens for actions that change data; same-origin checks
Abuse and spam Rate limiting per IP or user on the server
XSS when displaying results Insert with textContent or escape HTML
CORS errors The API must allow your origin; you can’t fix CORS from the browser side

Caching and performance#

  • Let the server set Cache-Control headers for data that rarely changes (this site’s search index is cached for 15 minutes).
  • Load data once and reuse it in memory (the quick search fetches its index only on first focus).
  • Use cache: 'no-store' for one-time tokens like captchas.
  • Paginate large datasets rather than loading thousands of records.

WordPress REST API examples#

/wp-json/wp/v2/posts?search=redirect      // search posts
/wp-json/wp/v2/categories                 // list categories
/wp-json/wp/v2/pages?slug=contact         // get a page by slug

Custom endpoints are registered in PHP with register_rest_route(), with a permission_callback that controls who can call them. More on APIs: REST APIs explained.

Fetch API FAQ#

Fetch or Axios?#

Fetch is built in and enough for most projects. Axios adds conveniences like interceptors and automatic JSON handling.

Why do I get a CORS error?#

The API server doesn’t allow requests from your domain. Configure CORS on the server, or call the API from your own backend.

Is content loaded with fetch indexed by Google?#

It can be, after rendering, but it’s less reliable. Keep SEO-important content in the initial HTML.

Found this useful? Share it

Join the discussion

Your email address will not be published. Required fields are marked *

Security code image. If you cannot read it, press refresh or contact me on WhatsApp.