← All posts

How to Add Web Browsing to a Custom GPT or Assistant

Quick answer: You add web browsing to a custom GPT by pointing a GPT Action at a fetch/search API using an OpenAPI schema, or by exposing the same API as a function-calling tool in your own code. For Claude and Cursor, the cleanest route is an MCP server. All three approaches are thin wrappers around the same two operations: search the web, fetch a page as clean text.

Custom GPTs can't browse the web on their own beyond ChatGPT's built-in browsing, which you don't control and can't tune. If you're building an assistant that needs to look things up, read documentation, or check live pages, you need to wire that in yourself. The good news is it's about 30 minutes of work.

The Three Integration Paths

There are three ways to give a model web access, and they map to where your assistant lives:

Approach Where it works Effort Best for
GPT Actions Custom GPTs in ChatGPT Low (paste a schema) No-code custom GPTs
Function calling Your own app (OpenAI, Anthropic, any API) Medium (write glue code) Production assistants
MCP Claude, Claude Code, Cursor, other MCP clients Low (paste a config) Agent tooling

All three need a backend that actually does the fetching. You can build one with Playwright and a proxy pool, or use a hosted API. I work at link.sc, so the examples use ours, but the wiring is the same for any fetch/search API.

Option 1: GPT Actions with an OpenAPI Schema

Custom GPTs support Actions: you paste an OpenAPI schema, and the GPT calls those endpoints when it decides it needs to. To give a custom GPT browsing, define two operations, fetch and search.

In the GPT editor, go to Configure, then Actions, then Create new action, and paste a schema like this:

openapi: 3.1.0
info:
  title: Web Fetch and Search
  version: "1.0"
servers:
  - url: https://link.sc
paths:
  /v1/fetch:
    get:
      operationId: fetchPage
      summary: Fetch any URL and return clean markdown
      parameters:
        - name: url
          in: query
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Page content as markdown
  /v1/search:
    get:
      operationId: searchWeb
      summary: Search the web, results include full page content
      parameters:
        - name: q
          in: query
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Search results with content

Then set Authentication to API Key, type Bearer, and paste your key (ours look like lsc_...). That's the whole integration. The GPT now decides on its own when to search and when to fetch, and you'll see the calls in the conversation.

Two tips from watching people do this. First, write instructions in the GPT's system prompt telling it when to browse ("if the user asks about anything recent or factual, use searchWeb first"). GPTs are conservative about calling Actions unless nudged. Second, keep the operation summaries specific, because that text is what the model uses to pick a tool.

Option 2: Function Calling in Your Own App

If you're building with the OpenAI or Anthropic API directly, you define the same two tools as functions and execute the HTTP calls yourself. The tool definition is boilerplate; the interesting part is the executor:

import requests

def fetch_page(url: str) -> str:
    r = requests.get(
        "https://link.sc/v1/fetch",
        params={"url": url},
        headers={"Authorization": "Bearer lsc_your_key"},
    )
    return r.json()["markdown"]

def search_web(query: str) -> list:
    r = requests.get(
        "https://link.sc/v1/search",
        params={"q": query},
        headers={"Authorization": "Bearer lsc_your_key"},
    )
    return r.json()["results"]

Register both as tools, and when the model returns a tool call, run the function and feed the result back. If you want the full agent-loop walkthrough, I wrote one in give your AI agent internet access.

One thing that matters more than people expect: return markdown, not raw HTML. A typical page is 100 KB+ of HTML that collapses to a few KB of markdown. That's the difference between blowing your context window on one page and reading five.

Option 3: MCP for Claude and Cursor

If your assistant is Claude, Claude Code, or Cursor, skip the custom glue entirely. MCP (Model Context Protocol) is the standard way to hand tools to these clients, and the config is a few lines:

{
  "mcpServers": {
    "linksc": {
      "url": "https://mcp.link.sc",
      "headers": {
        "Authorization": "Bearer lsc_your_key"
      }
    }
  }
}

That exposes search and fetch tools that the model can call natively. No schema authoring, no executor code. I covered the full setup, including Claude Desktop and Cursor specifics, in connecting Claude to the web with the link.sc MCP server.

Which One Should You Pick?

My honest take:

  • You're shipping a custom GPT for other people to use: GPT Actions. It's the only option ChatGPT supports, and the schema-paste workflow is genuinely fine.
  • You're building a product with an LLM inside it: function calling. You get full control over retries, caching, logging, and cost.
  • You (or your team) work in Claude or Cursor: MCP. It's the least code by a wide margin.

The mistake I see is people building the backend themselves before validating the assistant. Headless browsers, proxy rotation, and HTML cleaning are each their own project. Start with a hosted API, and if your volume later justifies building in-house, the tool interface you designed doesn't change, only the executor does.

What About Costs and Limits?

Whatever backend you choose, put guardrails on it. A browsing-enabled GPT will happily fetch 20 pages to answer one question if you let it. Things that have saved me money:

  • Cap tool calls per conversation turn (3 to 5 is usually plenty).
  • Instruct the model to search once, then fetch only the 1 or 2 most promising results.
  • Cache fetches for stable pages like documentation.

On the API side, link.sc's free tier is 500 credits a month, which is enough to build and test all three integrations before you think about pricing.

The Bottom Line

Adding web browsing to a custom GPT is not a research project anymore. Pick the path that matches your platform: OpenAPI Action for ChatGPT, function calling for your own app, MCP for Claude and Cursor. Point it at a fetch/search backend that returns clean markdown, add instructions about when to browse, and cap the call count. The whole thing fits in an afternoon.


Want to give your GPT or agent real web access? link.sc is one API for fetch and search, with an MCP server included. Get a free key with 500 credits a month.