# Instagram Story On-Screen Text Extractor (OCR) (`rainminer/instagram-story-text-extractor`) Actor

Read promo codes, CTAs, link-sticker URLs, and every on-screen overlay from public Instagram Stories with AI OCR. Paste Story or Highlight URLs—no login. Get structured JSON with text segments, language, and confidence. Export to JSON, CSV, Excel, or call via API.

- **URL**: https://apify.com/rainminer/instagram-story-text-extractor.md
- **Developed by:** [rainminer](https://apify.com/rainminer) (community)
- **Categories:** Social media, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.37 / 1,000 story processeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

The **Instagram Story Text Extractor** is an Apify Actor that reads public Instagram Stories and returns every piece of visible on-screen text as structured data—plus promo codes, call-to-action phrases, and link-sticker URLs when they appear on screen. Brands publish flash sales, coupon codes, and swipe-up links in Stories; this Actor turns that visual content into JSON you can search, monitor, and pipe into databases without watching Stories manually.

Each Story is analyzed with AI vision. Results land in one dataset row per Story with typed text segments, language detection, and confidence scores.

![Instagram](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Instagram_logo_2016.svg/320px-Instagram_logo_2016.svg.png)

***

### Key Features

- **On-screen text OCR**: Captures overlays, stickers, captions, hashtags, @mentions, promo banners, and CTA text.
- **Marketing fields**: Surfaces `promoCode`, `callToAction`, and `linkStickerUrl` when visible on the Story.
- **Video and image Stories**: Handles motion and still Stories from direct Story URLs or Highlight items.
- **Timestamp-aware (video)**: Records MM:SS when each text element first appears in video Stories.
- **Type classification**: overlay, caption, sticker, promo, cta, hashtag, mention, and more.
- **Multilingual**: ISO 639-1 language code per segment.
- **No login required**: Works with public Stories and Highlight items you can open without an account.

***

### What data can you extract?

| Field | Description |
| --- | --- |
| `storyUrl` | Canonical Instagram Story URL |
| `username` | Story owner handle (resolved from media metadata when the URL omits it) |
| `highlightId` | Highlight reel id when the URL is a Highlight item |
| `mediaId` | Instagram media id for the Story frame |
| `onScreenTextPlain` | Pipe-separated summary of marketing-relevant on-screen phrases (UI countdown filtered out) |
| `onScreenText` | Array of text segments with type, position, language, confidence |
| `promoCode` | Discount or coupon code if shown on screen |
| `callToAction` | Primary CTA phrase (e.g. Shop now) |
| `linkStickerUrl` | URL on a link sticker when visible |
| `mediaType` | `video` or `image` |
| `duration` | Length in seconds for video Stories |
| `scrapedAt` | ISO timestamp when the Story was processed |

***

### Who is it for?

- **Marketing and competitive intelligence** teams tracking promo codes and offers in Stories.
- **Affiliate and influencer analysts** capturing link-sticker destinations and campaign CTAs.
- **Retail and e-commerce** monitoring limited-time codes announced only in Stories.
- **Developers** building Story monitoring pipelines on Apify schedules and webhooks.

***

### How do I extract text from Instagram Stories?

1. Open the Actor on Apify Console and add **start URLs** — public Story or Highlight item URLs (`/stories/{username}/{id}/` or `/stories/highlights/{highlightId}/{id}/`).
2. Set **Max stories** (default 5) and keep **Apify Proxy** enabled if downloads fail from your region.
3. Run the Actor and open the **Dataset** tab for structured rows.
4. Export to JSON, CSV, Excel, or pull results via the Apify API.

***

### Input

```json
{
  "startUrls": [
    {
      "url": "https://www.instagram.com/stories/highlights/17975319242920589/3713636227774800082/"
    }
  ],
  "maxItems": 5
}
```

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `startUrls` | request list | — | Public Story or Highlight item URLs |
| `maxItems` | integer | `5` | Maximum stories to process per run |
| `proxyConfiguration` | object | Apify Proxy on | Proxy for Instagram media downloads |

***

### Output example

```json
{
  "storyUrl": "https://www.instagram.com/stories/brand/3456789012345678901/",
  "username": "brand",
  "mediaId": "3456789012345678901",
  "highlightId": null,
  "mediaType": "video",
  "duration": 12.5,
  "promoCode": "SAVE20",
  "callToAction": "Shop now",
  "linkStickerUrl": "https://example.com/sale",
  "onScreenText": [
    {
      "text": "SAVE20 — 20% off today only",
      "timestamp": "00:01",
      "type": "promo",
      "position": "center",
      "language": "en",
      "confidence": "high"
    }
  ],
  "scrapedAt": "2026-10-18T12:00:00.000Z"
}
```

***

### How it works

1. **Validate URLs** — each input URL is checked against Instagram Story and Highlight patterns.
2. **Download media** — the Story frame is retrieved without a browser session (video or image).
3. **AI extraction** — Gemini vision reads on-screen text and structured marketing fields.
4. **Dataset output** — one row per Story with segments and promo/CTA/link fields.
5. **Pay-per-event** — `story-processed` covers media handling; `story-text-processed` covers successful text extraction (separate from any media-only scrapers you run in parallel).

***

### Pricing

This Actor uses **pay-per-event** billing on Apify: you are charged when Story media is processed and again when text is successfully extracted to the dataset. Exact prices appear on the Actor detail page in Apify Store. Start with a small `maxItems` value to estimate cost per Story before scaling.

***

### Notes and limitations

- **Public Stories only** — private accounts and Stories that require login are not supported.
- **Media download** — Stories are fetched via Instagram’s logged-out guest session (`graphql/query` warm-up + `reels_media` + CDN download). No Instagram login or cookies in input. Use **Apify residential proxy** when datacenter IPs are blocked. Expired 24h Stories cannot be recovered.
- **Ephemeral Stories** — standard Stories expire after 24 hours; use a fresh URL or a Highlight item for stable tests.
- **OCR accuracy** — small, fast-moving, or low-contrast text may yield lower confidence.
- **Link stickers** — `linkStickerUrl` is set only when a URL is clearly visible on screen (not inferred from Instagram metadata alone).
- **Audio excluded** — spoken words are not transcribed; only visible text is extracted.

***

### Learn more

- [Apify Instagram Actors](https://apify.com/store?search=instagram)
- [Apify API docs](https://docs.apify.com/api/v2)

### Image Credit

Image credit: [Instagram](https://www.instagram.com/)

# Actor input Schema

## `startUrls` (type: `array`):

Public Instagram Story URLs to process. Accepts instagram.com/stories/{username}/{id}/ and stories/highlights/{highlightId}/{id}/ formats.

## `maxItems` (type: `integer`):

Maximum number of stories to process in a single run.

## `proxyConfiguration` (type: `object`):

Apify Proxy is used for Instagram Story downloads. Failed downloads are retried with a different proxy automatically.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.instagram.com/stories/highlights/17975319242920589/3713636227774800082/"
    }
  ],
  "maxItems": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.instagram.com/stories/highlights/17975319242920589/3713636227774800082/"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rainminer/instagram-story-text-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": [{ "url": "https://www.instagram.com/stories/highlights/17975319242920589/3713636227774800082/" }],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("rainminer/instagram-story-text-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.instagram.com/stories/highlights/17975319242920589/3713636227774800082/"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call rainminer/instagram-story-text-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rainminer/instagram-story-text-extractor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5QnfqLXfphIo3PQ1Z/builds/iNs65ir7EL0rooJFa/openapi.json
