Build a Grok Bot That Reads Instagram: Tool-Calling with the Scraper API
Grok can't open Instagram - but give it this API as a callable tool and a chatbot answers 'how are nasa's reels doing?' by fetching the data itself. The tool-call loop in ~40 lines, and why the same pattern works for GPT and Claude.
- /v1/profile/posts
- /v1/profile/reels
- /v1/post/comments
A bot that answers questions about Instagram has two halves: deciding what to look up, which a language model does well, and actually looking it up, which it cannot do at all - no model can log into Instagram or browse it. The fix is tool calling (function calling): you hand the model a menu of functions, it replies with which to run and the arguments, your code runs it against this API, and you feed the result back. xAI's Grok API is OpenAI-compatible, so the loop below is the same one you'd write for GPT and close to the one for Claude.
Why a prompt isn't enough
You can paste a profile's data into the prompt and ask Grok to analyse it - but then you did the fetching and the bot only works for data you already pulled. A tool lets the model fetch on demand: ask it anything about any public account and it decides which endpoint answers, calls it, and reads the JSON back - nothing about which account or metric is hard-coded ahead of time.
Define the API as one tool
Start with a single function that fronts a few endpoints, not one function per endpoint - a short menu is easier for the model to choose from. The schema names the endpoints it may hit and what target means (a handle for profile lookups, a post URL for comments). The description is the part the model actually reads to decide, so spell out when to reach for it.
The call-and-return loop
One turn is rarely enough: the model asks for a tool, you run it, you send the result back, and it either asks for another or writes the answer. So you loop - send the messages; if the reply carries tool_calls, run each and append the results as role: "tool" messages; repeat until it stops asking. The code below caps the rounds so a confused model can't spin forever.
Grok specifics
Point the OpenAI SDK at https://api.x.ai/v1 with your XAI_API_KEY and pick a current model such as grok-4. Because the API is OpenAI-compatible, the tools schema, the tool_calls on the reply and the role: "tool" messages are identical to OpenAI's - swapping to GPT is a base-URL and key change. Claude uses the same idea with a slightly different tool-block shape.
Keep the model honest about limits
Instagram hands a non-owner only a sample of some data, and the model won't know unless you tell it. Put the caps in the tool's description and pass the result's meta.notice straight back: follower and following lists cap around 50 for anyone but the owner, likers around 100, media URLs are signed and expire, private accounts are unreadable. Without that, a bot will cheerfully claim it exported 'all' 40,000 followers from the 50 it actually got.
From script to bot
The loop is the whole engine. Wrap answer(question) in whatever front end you like - a Telegram or Discord webhook, a Slack slash command, a web endpoint - and you have a bot that answers Instagram questions in plain language. Scrapes are live page loads, so keep the HTTP timeout generous (a big request can take a minute) and run the call off your web worker's main thread.
Full example (Python)
# A Grok chatbot that answers Instagram questions by calling this API.
# pip install openai requests | set XAI_API_KEY and RAPIDAPI_KEY
import json
import os
import requests
from openai import OpenAI
HOST = "YOUR-API-HOST.p.rapidapi.com"
IG_BASE = f"https://{HOST}"
IG_HEADERS = {"x-rapidapi-key": os.environ["RAPIDAPI_KEY"], "x-rapidapi-host": HOST}
grok = OpenAI(api_key=os.environ["XAI_API_KEY"], base_url="https://api.x.ai/v1")
MODEL = "grok-4"
# One tool fronting a few endpoints - a short menu is easier for the model.
TOOLS = [{
"type": "function",
"function": {
"name": "instagram",
"description": (
"Fetch public Instagram data. Use for any question about a public "
"account's posts or reels, or a post's comments. Non-owners get a "
"limited sample of some lists - report meta.notice honestly."
),
"parameters": {
"type": "object",
"properties": {
"endpoint": {
"type": "string",
"enum": ["profile/posts", "profile/reels", "post/comments"],
},
"target": {
"type": "string",
"description": "A handle like 'nasa' for profile/*, or a post URL for post/comments.",
},
"count": {"type": "integer", "default": 30},
},
"required": ["endpoint", "target"],
},
},
}]
def call_instagram(endpoint, target, count=30):
key = "post_url" if endpoint.startswith("post/") else "channel_url"
r = requests.get(
f"{IG_BASE}/v1/{endpoint}",
params={key: target, "count": count},
headers=IG_HEADERS,
timeout=330, # live page loads - give them room
)
return r.json()
def answer(question, max_rounds=5):
messages = [{"role": "user", "content": question}]
for _ in range(max_rounds):
reply = grok.chat.completions.create(
model=MODEL, messages=messages, tools=TOOLS
).choices[0].message
messages.append(reply)
if not reply.tool_calls:
return reply.content
for call in reply.tool_calls:
args = json.loads(call.function.arguments)
result = call_instagram(**args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result)[:12000], # trim to fit context
})
return "Stopped after too many tool calls."
if __name__ == "__main__":
print(answer("How are nasa's last 20 reels doing? Name the top 3 by views."))Replace YOUR-API-HOST and YOUR_RAPIDAPI_KEY with the values from the listing's Endpoints tab on RapidAPI.
Frequently asked questions
Can Grok read Instagram on its own?
No. Grok - like GPT and Claude - can't log into Instagram or browse it. It can decide what to look up and call a tool that does the fetching, which is exactly what this guide wires up.
Does this work with ChatGPT or Claude too?
Yes. Grok's API is OpenAI-compatible, so the tool schema and the call loop are the same for GPT - just change the base URL and key. Claude uses the same tool-calling idea with a slightly different message shape.
Which Grok model should I use?
Any current chat model with tool calling, e.g. grok-4. Set it in one place; the loop doesn't change with the model.
How many tools should I define?
Start with one function fronting a handful of endpoints. Models pick more reliably from a short menu; split into separate tools only once one function is juggling unrelated jobs.
What does it cost to run?
Two bills: xAI for the model tokens and this API for the data (a RapidAPI key with a free tier). The data calls are the slow part, not the tokens - cache results you expect to reuse.