You pointed a web app at localhost:11434 and got nothing back. No error in Ollama's logs, no crash, no useful message. The request died silently in your browser's console with a CORS policy error.
Ollama does serve browser requests out of the box, but only from a fixed list of origins, and localhost is on it. So the error is already telling you something: the page making the call is not on localhost. The fix is one environment variable.
How do you fix Ollama CORS on Mac?
Set OLLAMA_ORIGINS, one of Ollama's environment variables, to allow cross-origin requests. The fastest path:
launchctl setenv OLLAMA_ORIGINS "*" && pkill Ollama; open -a OllamaThat tells macOS to accept requests from any origin and restarts the Ollama process. You're unblocked in about five seconds.
That command resets at your next reboot. How you make it permanent depends on how Ollama runs, which is the step most guides get wrong. If you use the menu-bar app, launchd starts it and launchd never reads ~/.zshrc, so a shell export cannot reach it: re-run the launchctl setenv line after a reboot, or add a LaunchAgent that runs it at login. If you start the server yourself with ollama serve, it inherits that shell, so an export is the right tool:
export OLLAMA_ORIGINS="*"Add it to ~/.zshrc and start the server from a new terminal.
Want to name specific origins instead of the wildcard? List the ones that are not already covered:
launchctl setenv OLLAMA_ORIGINS "http://192.168.1.20:5173,http://myapp.test:8080"Comma-separated, no spaces, and include the port. One thing to know before reaching for this to lock Ollama down: the variable is additive. AllowedOrigins() appends the built-in list to whatever you set, so scoping adds your origin and never removes localhost. No value of OLLAMA_ORIGINS blocks a local page.
How do you verify the CORS fix worked?
Retry the request from the page that was failing. Do not test it from a console on a localhost page, because that origin is allowed by default and the call succeeds whether or not your change took effect:
fetch('http://localhost:11434/api/tags').then(r => r.json()).then(console.log)To check one specific origin from Terminal, send the preflight yourself and look for the Access-Control-Allow-Origin header, which Ollama returns only for an origin it accepts:
curl -si -X OPTIONS http://localhost:11434/api/tags -H "Origin: http://192.168.1.20:5173" -H "Access-Control-Request-Method: GET" | grep -i access-control-allow-originNo output means that origin is still rejected. Kill and restart: pkill Ollama; open -a Ollama.
Which origins does Ollama allow by default?
Ollama assembles the list in AllowedOrigins() in envconfig/config.go, and the built-in entries go on at every start. At v0.32.5 they are http and https on localhost, 127.0.0.1 and 0.0.0.0, each bare and on any port, plus the app://, file://, tauri://, vscode-webview:// and vscode-file:// schemes.
So a dev server on http://localhost:5173 reaches Ollama with nothing configured, and so does an Electron or Tauri shell. What is missing from that list is everything else: a LAN address like http://192.168.1.20:5173 that you opened from another machine, a custom hostname like http://myapp.test:8080, or a page served from a real domain. For those the browser sends a preflight OPTIONS, Ollama omits Access-Control-Allow-Origin, and the request dies before it fires.
The list is a boundary, not an oversight. Ollama's API can load and unload models, so the default trusts the machine it runs on and nothing past it. That is also why this wall tends to appear when you move a working local app to a LAN address or a staging domain, rather than on your first day with an Ollama frontend.
Common gotchas after applying the fix
The setting disappears after a reboot. launchctl setenv does not persist across restarts on macOS, so the wall comes back. A shell export is not the answer for the menu-bar app either, because launchd does not read ~/.zshrc. Persist it with a LaunchAgent that sets the variable at login, or re-run the launchctl setenv line after each reboot.
Homebrew-managed Ollama ignores shell variables. If you installed Ollama with brew services start ollama, it runs as a launchd service that doesn't inherit your shell environment. Edit the Homebrew plist, or set the variable at the system level with launchctl setenv. This is the same reason the menu-bar app ignores a shell export.
The setting works but requests still hang. If CORS is fixed (no browser error) but requests take forever, Ollama might be loading a model on first request. Large models (7B+) take 3-5 seconds to load from disk. Wait for the first response, and subsequent requests will be fast. If every one is slow and not just the first, the bottleneck is more likely memory than CORS - check a model against your hardware and drop to a size that fits.
The alternative: skip CORS entirely
ToolPiper bundles llama.cpp as its own inference engine - same models, same GGUF format, same Metal GPU speed. Because the browser connects to ToolPiper's HTTP server directly (which includes CORS headers natively), there's no environment variable to configure and nothing to reset after a reboot.
It also connects to Ollama as an external provider during the switch, so models you already pulled stay reachable while you migrate. A transition path, not the destination.
Download ToolPiper at modelpiper.com, or apply the fix above and keep using Ollama directly.
This is part of a series on Ollama frontends for Mac. Next: Ollama Chat Without Docker on Mac - native alternatives to Open WebUI.
