What Is Codex Web Search? Config, Tradeoffs, and the API Alternative

TLDR: OpenAI Codex has built-in web search, and for local chats it is on by default in cached mode, which serves results from an OpenAI-maintained index. Set web_search to cached, indexed, live, or disabled in config.toml, and use tools.web_search for domains and context size. To add a search tool you control, point Codex at the You.com MCP server with a url entry. No bridge is needed.
This guide covers what Codex searches with by default, what each mode changes, what the built-in tool does not do, and how to add the You.com MCP server or API. The facts come from OpenAI's Codex documentation as read in October 2026. Codex configuration changes often, so check the reference before you copy a key.
Is web search on by default in Codex?
Yes, for local chats. OpenAI's web search page says Codex enables cached search by default, and that cached mode uses an OpenAI-maintained index instead of fetching arbitrary pages live, which lowers but does not remove prompt injection risk. When Codex runs with full access, such as with the --yolo flag, search defaults to live results.
| web_search value | What the documentation says it does |
|---|---|
| cached (default) | Serves results from the web search cache, an OpenAI-maintained index of web results |
| indexed | Permits external web access only when the search index gates the request |
| live | Fetches the most recent data from the web, the same as the --search flag |
| disabled | Turns the web search tool off |
Codex reads personal defaults from ~/.codex/config.toml and project overrides from .codex/config.toml in trusted projects, per Config basics. The older features.web_search, features.web_search_cached, and features.web_search_request toggles are deprecated. The configuration reference maps the last two to cached and live only when web_search is unset. Administrators can restrict the allowed modes with allowed_web_search_modes in requirements.toml, and disabled is always allowed.
The setting belongs to the Codex host, not the client. OpenAI's docs say the IDE extension uses the connected host's search mode, and that the desktop app, the CLI, and the IDE extension share MCP configuration for the same host. Edit config.toml once per host and every client on it follows. Searches show up in each client's transcript, so you can see what ran.
# ~/.codex/config.toml
web_search = "cached" # default; also "indexed", "live", or "disabled"
[tools.web_search]
context_size = "medium" # low, medium, or high
allowed_domains = ["docs.python.org", "peps.python.org"]
What does tools.web_search control?
The tools.web_search table is where the steering lives. According to the configuration reference, its object form sets the search context size (low, medium, or high), the allowed search domains, and an approximate user location with country, region, city, and timezone fields.
One boundary matters for teams. OpenAI's docs describe web search as a hosted tool, separate from sandboxed command networking, and say search-domain filters do not restrict local command traffic, apps, connectors, or MCP servers. An allowed_domains list narrows the built-in tool only. It will not narrow any MCP search tool you add, so set domain rules on that server separately. Our site restriction guide covers the pattern on the API side.
The reference also lists no freshness window, news option, or per-call result count for the built-in tool. You pick a mode in config or with a flag for one run, not per query in code. And the output serves Codex rather than your software: it informs Codex's answers instead of handing a pipeline a JSON body of URLs, snippets, and dates.
How do you add the You.com MCP server to Codex?
Codex supports both stdio and streamable HTTP MCP servers, with bearer token and OAuth authentication for HTTP servers, according to OpenAI's MCP documentation. The hosted You.com server therefore needs only a url entry. A stdio bridge such as mcp-remote is sometimes suggested for remote servers, and with HTTP support Codex does not need one. The reference's note that streamable HTTP remote placement is not implemented applies to the experimental_environment setting, which moves stdio servers to a remote executor. It does not describe the HTTP transport.
# ~/.codex/config.toml
[mcp_servers.you-com]
url = "https://api.you.com/mcp?profile=free"
The profile=free parameter selects the keyless profile, which exposes the you-search and you-discover tools at 100 queries per day, per the You.com Codex CLI page. Start Codex and type /mcp to see the active servers.
For a key, use bearer_token_env_var. It names an environment variable that Codex sends as a bearer token, so the key stays out of the file. With a key, the /mcp endpoint also exposes you-contents and you-balance. The enabled_tools line below limits the server to search, so add you-contents if you want page extraction. You.com's page shows the same result with a literal Authorization header in an http_headers table. Headers belong in that table, not in a JSON-style headers object.
# ~/.codex/config.toml
[mcp_servers.you-com]
url = "https://api.you.com/mcp"
bearer_token_env_var = "YDC_API_KEY"
enabled_tools = ["you-search"]
[mcp_servers.you-com.tools.you-search]
output_token_limit = 4000 # illustrative budget for one call's output
Two more per-server settings suit a search tool, per the MCP documentation. The output_token_limit setting under tools sets a token budget for one tool's output, which caps how much a single search can add to the transcript. The 4000 above is an illustration, so size it to your sessions. And default_tools_approval_mode takes auto, prompt, writes, or approve, where writes prompts only for tools that are not marked read-only.
You.com also publishes a Codex plugin that installs four skills plus MCP server configs for the default, research, finance, and keyless discover endpoints. The skills tell Codex when to use each tool and how to cite what it finds. Codex invokes them with a $ mention.
# live search for one run
codex --search "Summarize the latest release notes for this dependency"
# install the You.com plugin (four skills plus the MCP server configs)
codex plugin marketplace add youdotcom-oss/agent-skills --sparse .agents/plugins
codex plugin add you@you-com
Should Codex use the built-in search or the MCP server?
Nothing in the documentation ranks the two when both are available, so decide on purpose. Three setups work:
- Built-in only. Leave the default, and run codex --search for tasks that need live data. This takes no setup.
- Both enabled. Codex can use either tool. Ask for the source of each claim, and read the transcript to see which tool ran.
- MCP only. Set web_search to disabled, which the reference says removes the tool, and keep one search tool whose parameters follow you across agents. The same server works in other clients, as our MCP setup guide shows.
| Question | Built-in web search | You.com MCP search |
|---|---|---|
| Setup | On by default for local chats, in cached mode | One url entry in config.toml |
| What the model sets per call | Nothing documented; mode and tools.web_search are set per session or run | query, count, freshness, offset, and exclude_domains, plus site: and filetype: operators in the query |
| Domain rules | tools.web_search.allowed_domains | Host-only include_domains and boost_domains; the model can set exclude_domains |
| Usage limits | No separate web search line item on OpenAI's pricing page | 100 queries per day on the free profile; a key lifts the limit |
The right column comes from the You.com MCP documentation. Host-only means your config sets the value and the model cannot change it.
Cost differs by route. OpenAI's pricing page describes plan usage and token rates and has no separate line item for web search. Search results still become part of the conversation, so they count as tokens, and a larger context_size can mean more of them. The You.com free profile allows 100 queries per day, and an API key lifts that limit.
To choose with evidence, ask each setup the same ten questions: three about releases from the last week, three about stable APIs, and four built from real error strings. For each answer, record whether it cited a primary source, whether the cited page carried a date, and whether the version matched yours. Then read the transcript to see how many searches each run used. Change one setting at a time, and keep the questions fixed.
When do you need the API instead?
Both the built-in tool and the MCP server answer questions inside a Codex session. When your product or pipeline needs live results as data, call the Web Search API directly. It takes one POST and returns a results object with a web array and, when the query has news intent, a news array. Web results carry url, title, description, and snippets. News results carry description and page_age. Our coding agent guide compares the routes.
curl -s -X POST https://ydc-index.io/v1/search \
-H "X-API-Key: $YDC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "postgresql 17 logical replication changes", "count": 5}'
What failure modes should you test for?
- Cached results on fast topics. Cached mode returns pre-indexed results instead of fetching live pages. For something that shipped this week, ask for the source and its date, or run codex --search or set live.
- Untrusted content. OpenAI says to treat all web results as untrusted input. Live retrieval exposes Codex to arbitrary pages, and cached mode only lowers the risk. Do not let search results trigger commands without review.
- Over-narrow domain lists. Pin allowed_domains to one docs site and Codex cannot search the changelog, the issue that matches your error, or a migration guide on another domain. Keep a test question whose answer lives outside the list, and check that Codex says so instead of guessing.
- Search theater. The model says it checked online, but no search happened. OpenAI's docs say searches appear as web_search items in the interactive transcript and in codex exec --json output, so look for them.
- Slow or failing MCP startup. The default startup timeout is 10 seconds and the default tool timeout is 60 seconds. Set required to true on a server only if a failed start should stop the session.
- Quiet config mistakes. A wrong key name, a bridge that is no longer needed, or a profile on the wrong path produces no obvious error.
The script below catches the quiet mistakes. It uses tomllib, which ships with Python 3.11 and later, and checks a config.toml for an invalid web_search mode or context_size, the deprecated feature toggles, a literal bearer token, a headers key Codex does not read, the free profile on a research or finance path, and the mcp-remote bridge. Save it as check_codex_config.py. Running python3 check_codex_config.py --selftest executes six offline tests. Running python3 check_codex_config.py ~/.codex/config.toml checks a real file and exits with 1 when it finds a problem.
#!/usr/bin/env python3
"""Check a Codex config.toml for web search and You.com MCP mistakes.
python3 check_codex_config.py ~/.codex/config.toml # Python 3.11+ (tomllib)
python3 check_codex_config.py --selftest
"""
import sys
import unittest
from urllib.parse import parse_qs, urlsplit
MODES = ("disabled", "cached", "indexed", "live")
SIZES = ("low", "medium", "high")
LEGACY = ("web_search", "web_search_cached", "web_search_request")
YOU_PATHS = ("/mcp", "/mcp/research", "/mcp/finance")
def check_server(name, entry):
problems = []
args = " ".join(str(a) for a in entry.get("args") or [])
if "mcp-remote" in args and "api.you.com" in args:
problems.append("%s: Codex connects to streamable HTTP servers directly; "
"drop the mcp-remote bridge and set url" % name)
parts = urlsplit(entry.get("url") or "")
if parts.netloc != "api.you.com":
return problems
if parts.path not in YOU_PATHS:
problems.append("%s: unexpected path %s" % (name, parts.path))
profile = parse_qs(parts.query).get("profile", [""])[0]
if profile in ("free", "discover") and parts.path != "/mcp":
problems.append("%s: ?profile=%s on %s lists no tools and returns no error"
% (name, profile, parts.path))
if "headers" in entry:
problems.append("%s: headers is not a Codex key; use http_headers or "
"bearer_token_env_var" % name)
auth = (entry.get("http_headers") or {}).get("Authorization", "")
if auth.startswith("Bearer ") and len(auth) > len("Bearer "):
problems.append('%s: literal bearer token; use bearer_token_env_var = "YDC_API_KEY"' % name)
return problems
def check(config):
problems = []
mode = config.get("web_search")
if mode is not None and mode not in MODES:
problems.append("web_search = %r; use one of %s" % (mode, ", ".join(MODES)))
for key in LEGACY:
if key in (config.get("features") or {}):
problems.append("features.%s is deprecated; use the top-level web_search setting" % key)
tool = (config.get("tools") or {}).get("web_search")
if isinstance(tool, dict) and tool.get("context_size") not in (None,) + SIZES:
problems.append("tools.web_search.context_size = %r; use low, medium, or high"
% tool["context_size"])
for name, entry in (config.get("mcp_servers") or {}).items():
problems.extend(check_server(name, entry))
return problems
class CheckTests(unittest.TestCase):
def parse(self, text):
import tomllib # Python 3.11+
return tomllib.loads(text)
def test_free_profile_and_keyed_blocks_are_clean(self):
free = '[mcp_servers.you-com]\nurl = "https://api.you.com/mcp?profile=free"\n'
keyed = ('web_search = "cached"\n[tools.web_search]\ncontext_size = "medium"\n'
'allowed_domains = ["docs.python.org"]\n[mcp_servers.you-com]\n'
'url = "https://api.you.com/mcp"\nbearer_token_env_var = "YDC_API_KEY"\n'
'enabled_tools = ["you-search"]\n')
self.assertEqual(check(self.parse(free)), [])
self.assertEqual(check(self.parse(keyed)), [])
def test_bad_mode_size_and_legacy_toggles(self):
text = ('web_search = "always"\n[features]\nweb_search_request = true\n'
'[tools.web_search]\ncontext_size = "huge"\n')
found = check(self.parse(text))
self.assertEqual(len(found), 3)
self.assertIn("deprecated", found[1])
def test_mcp_remote_bridge_is_flagged(self):
text = ('[mcp_servers.you-com]\ncommand = "npx"\n'
'args = ["-y", "mcp-remote", "https://api.you.com/mcp"]\n')
self.assertIn("directly", check(self.parse(text))[0])
def test_free_profile_on_research_path_lists_no_tools(self):
text = '[mcp_servers.r]\nurl = "https://api.you.com/mcp/research?profile=free"\n'
self.assertIn("lists no tools", check(self.parse(text))[0])
def test_headers_key_and_literal_token(self):
wrong = '[mcp_servers.y]\nurl = "https://api.you.com/mcp"\nheaders = { Authorization = "Bearer abc" }\n'
literal = ('[mcp_servers.y]\nurl = "https://api.you.com/mcp"\n'
'[mcp_servers.y.http_headers]\nAuthorization = "Bearer abc"\n')
self.assertIn("not a Codex key", check(self.parse(wrong))[0])
self.assertIn("literal bearer token", check(self.parse(literal))[0])
def test_other_servers_and_boolean_tool_setting_are_ignored(self):
text = 'tools.web_search = true\n[mcp_servers.x]\nurl = "https://example.com/mcp"\n'
self.assertEqual(check(self.parse(text)), [])
if __name__ == "__main__":
if "--selftest" in sys.argv:
unittest.main(argv=[sys.argv[0]], verbosity=2)
if len(sys.argv) != 2:
sys.exit("usage: python3 check_codex_config.py PATH-TO-config.toml")
import tomllib # Python 3.11+
with open(sys.argv[1], "rb") as fh:
result = check(tomllib.load(fh))
print("\n".join(result) if result else "ok: no quiet failures found")
sys.exit(1 if result else 0)
The tests cover the documented behaviors, not a live Codex session. No Codex or keyed You.com calls were made while writing this guide, so run /mcp in your own session and confirm the tools you expect are listed.
Related Guides
Frequently Asked Questions
Yes, for local chats. OpenAI's docs say Codex enables cached search by default, which serves results from an OpenAI-maintained index instead of fetching pages live. With --yolo or another full-access sandbox setting, search defaults to live. Set web_search to disabled in config.toml to turn the tool off.
OpenAI's pricing page describes plan usage and token rates and has no separate line item for web search. Search results still become part of the conversation, so they count as tokens, and a larger context_size can mean more of them. A You.com MCP server has its own limits: the free profile allows 100 queries per day, and an API key lifts that limit.
Yes. Codex supports streamable HTTP MCP servers, so a url entry under mcp_servers is enough and no stdio bridge is needed. Use https://api.you.com/mcp?profile=free for the keyless profile, or the /mcp endpoint with bearer_token_env_var set to the name of an environment variable that holds your key.
It depends on the job. The built-in tool needs no setup and is on by default, but you configure it per session and it returns text for Codex. The MCP server gives the model a search tool with per-call parameters and works across agents. Call the API directly when structured results must reach code you own.
LI Test
LI Test
Share Article:
Related resources.

What Is MCP Web Search? Live Results for Model Context Protocol Agents
October 12, 2026
Blog

How to Build LangGraph Integrations with the You.com Web Search API
October 7, 2026
Blog

How to Add Web Search to AutoGen Agents With the You.com MCP Server
October 2, 2026
Blog


