Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If a browser request from http://localhost:5050 to a mock API at http://localhost:3000 fails with “No Access-Control-Allow-Origin header is present,” register @fastify/cors on the Fastify instance before calling listen(). For a local request without credentials, allow the frontend origin—or use * if the mock is intentionally open. If the browser sends cookies or other credentials, use an explicit origin instead of *.

Why a mocked GET route fails across localhost ports

A browser origin consists of the scheme, hostname, and port. As a result, http://localhost:5050 and http://localhost:3000 are different origins even though both use localhost. The browser applies cross-origin resource sharing (CORS) rules to the request.

In a March 2025 Linux Foundation LFW111 forum report, a frontend at http://localhost:5050 fetched http://localhost:3000/confectionery and received the error “No ‘Access-Control-Allow-Origin’ header is present on the requested resource.” The poster reported that adding origin: "*" to their Fastify CORS configuration worked. That is a useful reproduction, not a controlled test. Read the forum report.

CORS is enforced by browsers. A route can respond successfully to curl or Postman while a browser refuses to expose that response to frontend JavaScript. The API response must include an Access-Control-Allow-Origin value that permits the requesting frontend origin.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Register CORS before starting Fastify

Install the @fastify/cors package if it is not already in the project, then register it on the same Fastify instance that defines the mock route. The plugin adds an onRequest hook and a wildcard OPTIONS route; registering before listen() ensures it is in place when requests arrive. See the official @fastify/cors README.

import Fastify from 'fastify'
import cors from '@fastify/cors'

const fastify = Fastify()

await fastify.register(cors, {
  origin: 'http://localhost:5050',
  methods: ['GET', 'HEAD', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization']
})

fastify.get('/confectionery', async () => ({
  items: []
}))

await fastify.listen({ port: 3000 })

Replace the example frontend origin and route with the values used by your app. The configuration explicitly allows the listed methods and headers; add any method or request header your frontend actually uses. The plugin documentation lists origin, methods, allowedHeaders, credentials, and preflight options, and documents * as the default origin plus GET,HEAD,POST as the default methods. See its options documentation.

Choose an origin policy that matches the request

Request setup Origin configuration What to know
Open local mock; no credentials origin: '*' The plugin documents the wildcard as its default. Browsers can accept it for requests without credentials.
Frontend at a known origin; no credentials origin: 'http://localhost:5050' Allow the frontend origin explicitly; include the correct scheme and port.
Cookies or fetch with credentials: 'include' Explicit frontend origin and credentials: true Do not combine credentialed browser requests with Access-Control-Allow-Origin: *. The response also needs Access-Control-Allow-Credentials: true.

For example, configure credentials deliberately when cookies are part of the flow:

await fastify.register(cors, {
  origin: 'http://localhost:5050',
  credentials: true
})

With credentials enabled, the browser requires an explicit allowed origin and the credentials response header; a wildcard origin is not valid. See MDN’s Access-Control-Allow-Origin reference and Access-Control-Allow-Credentials reference.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Know when a GET triggers an OPTIONS preflight

A simple cross-origin GET is normally sent without a preflight. However, a browser may send an OPTIONS request first when the request uses non-simple features, such as certain custom headers. The server’s preflight response must allow the intended method and requested headers. MDN describes the browser’s preflight flow and the Access-Control-Allow-Methods and Access-Control-Allow-Headers response headers in its preflight request guide.

Credentials have a separate requirement: even when a GET is not preflighted, a credentialed response needs Access-Control-Allow-Credentials: true before browser code can read it. See MDN’s CORS guide.

Debug the missing CORS header

  1. Record both origins. Note the frontend and API scheme, hostname, and port. A port difference makes the origins distinct.
  2. Inspect the actual GET response. In browser DevTools, open the Network panel and check whether its response includes Access-Control-Allow-Origin with the frontend origin or an acceptable wildcard for a non-credentialed request.
  3. Look for an OPTIONS request. If one appears before the GET, inspect its Access-Control-Request-Method and Access-Control-Request-Headers request headers. Confirm the preflight response allows that method and those headers.
  4. Check plugin placement and instance. Ensure @fastify/cors is registered on the same Fastify instance as the route and before listen().
  5. Check credential settings. If the frontend sends cookies or uses credentials: 'include', use an explicit origin and enable credentials deliberately; do not use *.
  6. Test route availability separately. Try curl or Postman to determine whether the endpoint responds. These clients do not reproduce browser CORS enforcement, so a successful direct request does not prove the browser configuration is correct.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Global plugin settings or a route-specific override?

Registering the plugin globally is a straightforward choice when the mock API shares one CORS policy. The plugin also supports route-level CORS configuration when a particular route needs a different policy; consult its route configuration documentation. Avoid broadening access just to silence an error: allow the frontend origin and the methods and headers the browser actually requests.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.