Access real-time data from Claude API

6 min read Original article ↗

Tools allow Claude to interact with external APIs, databases, and services to fetch real-time information and perform actions beyond its built-in knowledge.

Official documentation on Claude Tools

In this tutorial, we’ll explore how to use the tool use feature (also called function calling) with Claude, using the SerpApi Google Maps API as a practical example.

You can use any API, in this example, I’m using an API from SerpApi.

Think of tools as functions that Claude can call when it needs to accomplish specific tasks. Instead of just responding with text, Claude can:

  • Search Google Maps for nearby restaurants

  • Check current weather data

  • Query databases

  • Fetch stock prices

  • And much more!

We have a getting started blog post to start using Claude API with Python

Let’s say we try to get a real-time data like this:

message = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1000,
    messages=[
        {
            "role": "user",
            "content": "Top 3 cafes with up to date rating from Google Maps in Jakarta"
        }
    ]
)

Here is the answer:

claude try to access real-time data

While it still answers the prompt, it includes a disclaimer that they don’t have access to a real-time data.

Prerequisites

Before we begin, make sure you have:

  • Python 3.7 or higher installed

  • An Anthropic API key (get one here)

  • A SerpApi API key (sign up here)

  • The Anthropic Python SDK installed

pip install anthropic requests python-dotenv

First, let’s define a tool that Claude can use. A tool definition tells Claude:

  1. What the tool does

  2. What parameters it needs

  3. What format those parameters should be in

Here’s how we define a Google Maps search tool:

import os
import json
import requests
from anthropic import Anthropic
from dotenv import load_dotenv

load_dotenv()
client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))

# Define the tool
tools = [
    {
        "name": "search_google_maps",
        "description": "Searches for places on Google Maps based on a query and location. Returns information about businesses, restaurants, attractions, and other points of interest.",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "The search query (e.g., 'pizza restaurants', 'hotels', 'gas stations')"
                },
                "location": {
                    "type": "string",
                    "description": "The location to search in (e.g., 'New York, NY', 'London, UK')"
                }
            },
            "required": ["query", "location"]
        }
    }
]

Next, we need to create the actual Python function that calls the SerpApi:

# SerpApi (or any external API) actual function
def search_google_maps(query, location):
    # Find top results from Google Maps using SerpApi
    SERPAPI_KEY = os.environ.get("SERPAPI_API_KEY")
    
    params = {
        "engine": "google_maps",
        "q": query,
        "location": location,
        "z": "14", #zoom level
        "api_key": SERPAPI_KEY
    }
    
    try:
        response = requests.get("https://serpapi.com/search", params=params)
        response.raise_for_status()
        data = response.json()
        
        # Extract relevant information
        results = []
        if "local_results" in data:
            for place in data["local_results"][:5]:  # Get top 5 results
                results.append({
                    "title": place.get("title", "N/A"),
                    "rating": place.get("rating", "N/A"),
                    "address": place.get("address", "N/A"),
                    "type": place.get("type", "N/A")
                })
                
        return json.dumps(results)
    
    except Exception as e:
        return json.dumps({"error": str(e)})

Now comes the magic! We create a conversation loop where:

  1. We send a message to Claude with the available tools

  2. Claude decides if it needs to use a tool

  3. We execute the tool and send the results back to Claude

  4. Claude provides a final answer to the user

def chat_with_tools(user_message):
    messages = [{"role": "user", "content": user_message}]
    
    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        tools=tools,
        messages=messages
    )

    while response.stop_reason == "tool_use":
        # Extract tool use from response
        tool_use = next(block for block in response.content if block.type == "tool_use")
        tool_name = tool_use.name
        tool_input = tool_use.input
        
        print(f"\n🔧 Claude is using tool: {tool_name}")
        print(f"📥 With parameters: {tool_input}")
        
        # Execute the tool
        if tool_name == "search_google_maps":
            tool_result = search_google_maps(
                query=tool_input["query"],
                location=tool_input["location"]
            )
        
        print(f"📤 Tool returned: {tool_result[:200]}...")
        
        # Continue the conversation with tool result
        messages = [
            {"role": "user", "content": user_message},
            {"role": "assistant", "content": response.content},
            {
                "role": "user",
                "content": [
                    {
                        "type": "tool_result",
                        "tool_use_id": tool_use.id,
                        "content": tool_result,
                    }
                ],
            },
        ]
        
        # Get Claude's final response
        response = client.messages.create(
            model="claude-sonnet-4-20250514",
            max_tokens=1024,
            tools=tools,
            messages=messages
        )
    
    # Extract final text response
    final_response = next(
        (block.text for block in response.content if hasattr(block, "text")),
        None,
    )
    
    return final_response

Step 4: Putting It All Together

Here’s a complete example you can run:

# Example usage
if __name__ == "__main__":
    user_query = "Find me the best Italian restaurants in San Francisco"
    
    print(f"👤 User: {user_query}\n")
    response = chat_with_tools(user_query)
    print(f"\n🤖 Claude: {response}")

Example Output

👤 User: Find me the best cafe in Jakarta


🔧 Claude is using tool: search_google_maps
📥 With parameters: {'query': 'best cafe', 'location': 'Jakarta, Indonesia'}
📤 Tool returned: [{"title": "Giyanti Coffee Roastery", "rating": 4.6, "address": "Surabaya St No.20, RT.15/RW.5, Menteng, Central Jakarta City, Jakarta 10310, Indonesia", "type": "Cafe"}, {"title": "Kawisari Cafe & Ea...

🤖 Claude: Based on my search for the best cafes in Jakarta, here are some top-rated options:

**Top Recommendations:**

1. **Titik Koma Tanjung Duren** (4.8/5 rating)
   - Location: West Jakarta (Jl. Tanjung Duren Utara V No.246)
   - Known as a coffee shop with excellent reviews

2. **The Bènsara Cafe** (4.8/5 rating)
   - Location: South Jakarta (Jl. Manggarai Utara 1 No.B 9, Manggarai)
   - Highly rated cafe with great atmosphere

3. **TOMORO COFFEE - Sabang** (4.8/5 rating)
   - Location: Central Jakarta (Jl. H. Agus Salim No.62, Menteng)
   - Popular coffee shop in the Sabang area

4. **Giyanti Coffee Roastery** (4.6/5 rating)
   - Location: Central Jakarta (Surabaya St No.20, Menteng)
   - Coffee roastery with fresh beans and quality brews

5. **Kawisari Cafe & Eatery** (4.5/5 rating)
   - Location: Central Jakarta (Jl. Kebon Sirih No.77A, Menteng)
   - Cafe and eatery combination

All of these cafes have excellent ratings (4.5+ stars) and are located in prime areas of Jakarta. The top three with 4.8-star ratings would be my strongest recommendations, with Titik Koma Tanjung Duren, The Bènsara Cafe, and TOMORO COFFEE being standout choices.
...

Key Concepts to Remember

  1. Tool Definition: You describe what the tool does and what inputs it needs

  2. Tool Execution: You write the actual function that performs the action

  3. Tool Loop: Claude may need multiple back-and-forth exchanges to complete a task

  4. Tool Results: Always return results as strings (often JSON-formatted)

Best Practices

  • Clear descriptions: Make your tool descriptions detailed so Claude knows when to use them

  • Error handling: Always include try-catch blocks in your tool functions

  • Rate limiting: Be mindful of API rate limits when making external calls

  • Security: Never expose API keys in your code - use environment variables

Next Steps

Now that you understand the basics, try:

  • Adding multiple tools (weather, news, database queries)

  • Creating more complex tool chains where Claude uses multiple tools in sequence

  • Building a chatbot that can access your company’s internal APIs