# Instagram Reel Transcript Scraper API (`shakamize/instagram-transcript-scraper`) Actor

Transcribe Instagram reels with a large speech model. Every row carries a receipt: the media id, the seconds and bytes transcribed against what the manifest declared, and whether the model heard real speech rather than inventing it. Word timestamps, SRT, WebVTT, translation.

- **URL**: https://apify.com/shakamize/instagram-transcript-scraper.md
- **Developed by:** [Shakamize](https://apify.com/shakamize) (community)
- **Categories:** Social media, AI
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 minute of transcribed audios

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Instagram Reel Transcript Scraper API

Turns an Instagram reel into text: the full transcript, timestamped segments,
SRT and WebVTT subtitle files, and the detected language. Give it reel URLs or
bare shortcodes; no Instagram account is involved at any step.

Priced **per minute of transcribed audio**, rounded up, at $0.010. Most reels
are one minute. A post with no audio - a photo, a carousel, a video with a
silent track - is reported as such and **never charged**.

Two competitors already bill by audio time rather than per reel, and the nearest
of them charges the equivalent of **$0.06 a minute**. Billing this way is what
lets a three-minute interview and a ten-second clip both be priced honestly.

### What makes this different: the receipt

Transcription actors are easy to write and hard to trust. The complaints on this
field's worst-rated listing are `Actor returns cached/incorrect transcripts
instead of processing provided URL` and `First words missing from transcript`,
and neither is something a caller can check from a transcript alone.

A provenance field saying "captions or ASR" would not help, because on Instagram
there are no captions: nothing in a reel page carries a subtitle track, so
speech recognition is the only path and the label would be a constant.

So every row carries the numbers that make both failures decidable:

| Field                            | What it settles                                         |
| -------------------------------- | ------------------------------------------------------- |
| `mediaId`                        | Which media this transcript came from                   |
| `manifestDurationSeconds`        | How long Instagram said the media was, before any fetch |
| `audioSecondsTranscribed`        | How many seconds the model reported hearing             |
| `manifestAudioBytes`             | How many bytes of audio Instagram declared              |
| `audioBytesTranscribed`          | How many bytes were actually downloaded and sent        |
| `model`                          | Which speech model produced the text                    |
| `language` / `languageWasForced` | What it heard, and whether you told it what to expect   |

If `audioSecondsTranscribed` is short of `manifestDurationSeconds`, part of the
reel is missing from the transcript and you can see it. If `mediaId` is not the
reel you asked for, you can see that too. The first two numbers come from
Instagram's own manifest, read **before** anything is downloaded.

```json
{
  "shortcode": "DcozHIETCd9",
  "mediaId": "3974651461224900477",
  "ownerUsername": "nasaadmin",
  "language": "English",
  "languageWasForced": false,
  "model": "whisper-large-v3-turbo",
  "manifestDurationSeconds": 114.426483,
  "audioSecondsTranscribed": 114.45256192,
  "manifestAudioBytes": 1028427,
  "audioBytesTranscribed": 1028427,
  "billedMinutes": 2
}
```

### Word-level timestamps, segments, SRT and WebVTT

Every transcript can come back four ways at once: as continuous text, as timed
segments, as a start and end for **every individual word**, and as SRT or WebVTT
files wrapped at whatever line length your player needs. Word timings are what
caption burn-in and word-by-word overlays run on.

```json
{ "start": 0.62, "end": 0.82, "word": "Ladies" }
```

### How to translate an Instagram reel transcript to English

Ask for English and you get English whatever was spoken. Translation runs on a
larger, slower model, because it is the only one that will translate at all, so
a translated run bills under the higher-priced translated-minute event and every
row says `translatedToEnglish`. Word timings are not available when translating,
because the vendor's translation endpoint does not produce them.

**There is no model choice, deliberately.** The larger model is not the better
one: measured over the same six reels it rendered 56 seconds of English
interview **as Welsh**, and invented text on two quiet reels where the default
returned almost nothing. Offering it behind a field labelled "accurate" would
have sold a quality claim the measurement contradicts, so it is reached by
asking for a translation and by nothing else.

### Invented transcripts, and how you can tell

Speech models do not fail quietly on audio with no speech in it. **They
invent.** Measured on real reels:

| Reel                           | What came back                          |
| ------------------------------ | --------------------------------------- |
| A wildlife trailer, music only | "We are the Yamato! We are the Yamato!" |
| Ambient spacewalk footage      | "Copyright (c) 2020 Mooji Media Ltd."   |
| A fragrance advert, music only | "you"                                   |

None of that is in the audio. It is the single worst failure a transcript can
have, because nothing downstream can distinguish it from a real one - and it is
the failure the cheap actors in this field ship silently.

Every row therefore carries the model's **own** confidence, and a flag derived
from it:

```json
{ "speechDetected": false, "meanLogProb": -1.932, "text": "you" }
```

Measured across real reels, genuine speech runs **-0.17 to -0.22** and invented
text runs **-0.52 to -1.93**, so the two do not overlap. Set **Omit reels with
no real speech** to drop those rows entirely.

### A large model, and what it still gets wrong

Model size is the difference between a transcript and a guess. On the same reel
audio, a small model wrote "yoghurt" for "Jokic" and dropped the first 40
seconds of a clip. This actor runs only large models, and puts the model name on
every row.

**It is still not right about unusual proper nouns, and you should not assume it
is.** Measured on our own output, on a reel where every other word is correct
and the confidence is healthy:

| Spoken         | Returned         |
| -------------- | ---------------- |
| Reid Wiseman   | "Reed Weisman"   |
| Victor Glover  | "Victor Blummer" |
| Christina Koch | Christina Koch   |
| Jeremy Hansen  | Jeremy Hansen    |

So: **sentence structure, ordinary words and timings are reliable. Names,
brands and jargon are not.** `speechDetected` catches a transcript that was
invented wholesale; it cannot catch a single wrong name inside an otherwise
good one, and it will read `true` on the transcript above. If names matter for
your use, treat them as needing a second source.

We tested biasing the model with a supplied vocabulary list, which is the
obvious fix and what a competitor advertises. **It made things worse on every
reel measured** - it never corrected a name, it lowered confidence on 3 of 3,
once deleted 28% of a transcript, and once appended a spam URL that was not in
the audio. So the actor does not offer it.

### Costs are known before anything is downloaded

Instagram serves each reel a DASH manifest that declares the duration and the
byte length of an **audio-only** track - about a thirteenth of the size of the
video. This actor reads that manifest first, so:

- **Skip reels longer than** refuses a long reel without downloading it, and
  charges nothing for it.
- The audio is fetched straight from Instagram's CDN, with **no proxy at all**.
  The proxy only ever carries the page.

### Batch input, and no silent drops

Pass as many reels as you like in one run. Every reel you ask for produces
exactly one row - a transcript, or a record saying why there is none. A run
never returns fewer reels than you asked for while reporting success, and an
entry that cannot be read stops the run naming it rather than being skipped.

### Costing a run before you start it

Because the manifest declares a reel's duration before anything is downloaded,
**Skip reels longer than** and **Skip reels shorter than** both cost nothing to
apply. A three-second clip still costs a whole billed minute, so the minimum is
the field that stops a list of trailers being charged like a list of interviews.

### Input reference for every Instagram transcript setting

| Field                       | What it does                                                       |
| --------------------------- | ------------------------------------------------------------------ |
| `reelUrls`                  | Reel URLs, post URLs, or bare shortcodes                           |
| `maxItems`                  | Stop after this many reels                                         |
| `maxDurationSeconds`        | Skip anything longer, without downloading it                       |
| `minDurationSeconds`        | Skip anything shorter, without downloading it                      |
| `skipPostsWithoutAudio`     | Leave photos and carousels out of the dataset entirely             |
| `skipLowConfidence`         | Leave out reels the model says carry no real speech                |
| `speechConfidenceThreshold` | How strict the no-real-speech check is                             |
| `language`                  | Force an ISO-639-1 code. Empty means detect                        |
| `translateToEnglish`        | English out, whatever was spoken                                   |
| `timestampGranularity`      | Segments, words, both, or neither                                  |
| `subtitleFormats`           | SRT, WebVTT, or neither                                            |
| `subtitleMaxCharsPerLine`   | Wrap cues at your player's line width                              |
| `textFormat`                | One continuous block, or paragraphs on segment boundaries          |
| `includeCaption`            | The caption the poster wrote                                       |
| `includeEngagement`         | Likes and comments. Hidden comes back null, never zero             |
| `includeCaptionEntities`    | Hashtags and mentions, pulled out as lists                         |
| `includeAltText`            | Instagram's own description of what is on screen                   |
| `includeTopics`             | Instagram's topic labels, for grouping a batch                     |
| `includeLocation`           | The tagged place, with coordinates                                 |
| `includeMediaUrls`          | The audio, video and thumbnail URLs                                |
| `includeOwnerProfile`       | The poster's profile. Personal data, off by default                |
| `includeTaggedUsers`        | Accounts tagged in the post. Personal data, off by default         |
| `includeCoauthors`          | Credited co-authors. Personal data, off by default                 |
| `maxConcurrency`            | How many reels to work on at once                                  |
| `proxyConfiguration`        | Defaults to Apify Proxy's datacenter pool, which is all this needs |

### FAQ

#### How do I know the transcript is real and not invented?

Read `speechDetected`. Speech models will confidently produce text for audio that
has no speech in it, and a wrong transcript is worse than no transcript, because
nothing downstream can tell.

On a run on 2026-09-01, a 50-second reel with no speech produced the text
`"Thank you. Thank you."` across two segments. Its mean log probability was
**-0.52**, `speechDetected` came back **false**, and the run said so:

```
WARN  DcMXl1IPNtB: the model reports no real speech (mean log probability -0.52).
      The text it returned may be invented; speechDetected is false on the row.
```

The other reel in the same run, 114.5 seconds of actual speech, scored **-0.22**
with 27 segments and 289 words. Set `skipLowConfidence: true` to drop the
doubtful ones instead of receiving them flagged.

#### How do I work out what a run will cost before paying for it?

The reel page declares the audio duration and byte length before anything is
fetched, so a run can size itself in advance. Both land on the row as
`manifestDurationSeconds` and `manifestAudioBytes`, next to what was actually
transcribed.

Billing is per minute of audio, rounded up per reel. In the run above, a 114.5
second reel billed 2 minutes and a 50.2 second reel billed 1, for 3 billed
minutes total, and the run states it: `Billed 3 minute(s)`.

`maxDurationSeconds` and `minDurationSeconds` cap it before transcription rather
than after.

#### Which model does it use, and does the tier matter?

`whisper-large-v3-turbo`, and the tier matters more than it looks. Smaller
Whisper tiers were tested and rejected: `base` wrote "yoghurt" for "Jokic", and
`small` silently dropped the first 40 seconds of a clip. Only `large-v3-turbo`
was usable.

A hosted large model costs less than a locally run small one, so quality and cost
point the same way here.

#### What formats can I get the transcript in?

Continuous text, per-segment and per-word timestamps, SRT and WebVTT, controlled
by `textFormat`, `timestampGranularity` and `subtitleFormats`. A single run can
emit several at once, and `subtitleMaxCharsPerLine` sets the subtitle line
width.

#### What happens to posts with no audio?

They are reported rather than silently dropped. The run's closing line accounts
for every input:

```
INFO  Stored 2 record(s): 2 transcript(s), 0 post(s) with no audio, 0 too long,
      0 too short and 0 omitted for carrying no real speech.
```

`skipPostsWithoutAudio` drops them from the output if you would rather not see
them. Note that photo posts have no audio to transcribe at all; in one sample,
14 of 35 Instagram posts were photos.

#### Do I need a login or cookies?

No. Reel pages and the audio itself are read without an authenticated session.

### What it does not do

- **Private accounts, stories and highlights.** Only public posts are reachable
  without an account, and this actor never uses one.
- **Profiles.** It takes reels, not usernames. Profile listing pages need a
  residential proxy where reel pages do not, so crawling a profile would make
  every run cost about forty times as much per byte for the listing step.
- **Music attribution.** Instagram serves `music_info` as null to every client
  without an account - measured on 12 reels across five accounts - so there is
  no music field rather than one that is always empty.

A reel with music and no speech transcribes to little or nothing. That is the
correct answer for it, and it is still a minute of audio the model listened to.

### Telemetry

The Actor reports run health to its maintainer: error codes, the build number,
and per-field counts. On a failure it also sends a capped sample of the failed
requests, including **the Instagram URL you asked for**. It carries no personal
data, but it is your input, and this section says so rather than leave you to
find out. Your proxy configuration and the transcripts themselves are never
sent.

# Actor input Schema

## `reelUrls` (type: `array`):

The reels you want transcribed. Accepts a reel URL (<code>https://www.instagram.com/reel/Dcoz.../</code>), a post URL (<code>/p/…</code>), a profile-scoped one (<code>/nasaadmin/reel/…</code>) or a bare shortcode (<code>DcozHIETCd9</code>). An entry that cannot be read stops the run naming it, rather than being skipped quietly. Only <b>public</b> posts are reachable, and a post that turns out to be a photo or a carousel is reported as having no audio and costs nothing.

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

Stop after this many reels, counted over the whole list. Prefilled with the two prefilled reels so a first run is cheap to try; raise it once you paste your own list, or leave it empty to transcribe everything you passed.

## `maxDurationSeconds` (type: `integer`):

Skip any reel longer than this, charging nothing for it. Instagram's manifest declares the duration <b>before</b> the audio is fetched, so a reel past the limit costs no download and no transcription at all. Leave empty for no limit. Reels ran 7.5 to 197.9 seconds over a measured sample of 21, with a median of 43.3, so most reels are one billed minute.

## `minDurationSeconds` (type: `integer`):

Skip anything shorter than this. A three-second clip still costs a whole billed minute, so this is the field that stops a list of trailers from being charged like a list of interviews. Also read from the manifest, so a skipped reel is never downloaded.

## `skipPostsWithoutAudio` (type: `boolean`):

By default a photo, a carousel or a silent video still produces a row explaining that there was nothing to transcribe, so every reel you asked for leaves a trace. Turn this on to leave them out of the dataset entirely. Either way they are never charged.

## `skipLowConfidence` (type: `boolean`):

Speech models do not fail quietly on audio with no speech in it - they invent. Measured on real reels, a wildlife trailer came back as "We are the Yamato!" and a fragrance advert as the single word "you". Every row carries <code>speechDetected</code> and the model’s own <code>meanLogProb</code> so you can see it; turn this on to leave those rows out altogether. Unlike a post with no audio, these <b>are</b> charged, because the audio was fetched and put through the model.

## `speechConfidenceThreshold` (type: `string`):

Where to draw the line for <code>speechDetected</code>, on the model’s own confidence scale. Measured over real reels, genuine speech runs -0.17 to -0.22 and invented text runs -0.52 to -1.93. <b>Balanced</b> sits in the gap between them and is the default; <b>strict</b> flags anything with a hint of doubt; <b>lenient</b> flags only clear invention. The default is derived from six reels, which is enough to place it and not enough to make it right for every kind of audio.

## `language` (type: `string`):

A two-letter ISO-639-1 code (<code>en</code>, <code>es</code>, <code>pt</code>) to tell the model what it is listening to. Leave empty to let it detect, which is the default. Every row records the language and whether it was forced, so a wrong detection is visible rather than silent. Ignored when translating, which always produces English.

## `translateToEnglish` (type: `boolean`):

Return the transcript in English whatever was spoken. This runs on a larger, slower model, because it is the only one the vendor will translate with, so a run with this on bills under the <b>higher-priced</b> translated-minute event. Word timings are not available when translating. Every row records that it was translated.

## `timestampGranularity` (type: `array`):

<b>Segment</b> gives the transcript split into timed phrases. <b>Word</b> gives a start and end for every word, which is what caption burn-in and karaoke-style overlays need. Selecting neither returns the plain text only; the SRT and WebVTT files are built from segments regardless.

## `subtitleFormats` (type: `array`):

Render the transcript as subtitle files on the row. SRT is on by default; WebVTT is the browser-native form. Selecting neither leaves both fields null.

## `subtitleMaxCharsPerLine` (type: `integer`):

Wrap subtitle cues at this many characters. Players shrink or clip a line that overflows rather than wrapping it, so the limit has to be in the file. 42 is the broadcast convention and the default.

## `textFormat` (type: `string`):

How the full transcript is laid out. <b>Continuous</b> is one block, which is what you want for search and summarisation. <b>Paragraphs</b> breaks on the model’s own segment boundaries, which reads far better when a person is going to read it.

## `includeCaption` (type: `boolean`):

The caption the poster wrote, which is unrelated to what is spoken in the reel.

## `includeEngagement` (type: `boolean`):

Like and comment counts. A poster can hide the like count, and hidden comes back as null rather than as zero - reporting a withheld count as 0 would state a fact Instagram never published.

## `includeCaptionEntities` (type: `boolean`):

The hashtags and @mentions written in the caption, pulled out as lists so a batch can be grouped without reading every caption. Instagram publishes no entity list to a logged-out client, so these are read off the caption text itself.

## `includeAltText` (type: `boolean`):

Instagram’s own generated description of what is on screen, which often names text burnt into the video. It is the nearest thing available to on-screen text, and it comes from the page rather than from the transcript.

## `includeTopics` (type: `boolean`):

Instagram's own topic labels for the post, which are useful for grouping a batch without reading every transcript.

## `includeLocation` (type: `boolean`):

The place the poster tagged, with its coordinates where Instagram publishes them.

## `includeMediaUrls` (type: `boolean`):

The audio file this transcript came from, the full-quality video, and the thumbnail. These are signed URLs that expire within hours. Nothing extra is downloaded to produce them.

## `includeOwnerProfile` (type: `boolean`):

The poster's display name, verification and profile picture. A person's name and photo are personal data, protected by GDPR in the EU and by comparable rules elsewhere. Enable this only if you have a legitimate basis for collecting it. Off by default; the username is on every row regardless.

## `includeTaggedUsers` (type: `boolean`):

The accounts tagged in the post, with their display names. Personal data on the same footing as the poster's profile, so off by default.

## `includeCoauthors` (type: `boolean`):

Accounts credited as co-authors of the reel. Personal data, so off by default.

## `maxConcurrency` (type: `integer`):

How many reels to work on at once, up to 20. Raising it shortens a large run but does not reduce what it costs, because the billed unit is audio rather than time. Lower it if Instagram starts throttling a very large batch.

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

Defaults to Apify Proxy's automatic pool, which is datacenter and is the cheapest thing that works: reel pages were served over datacenter exits on 8 attempts out of 8, measured 2026-08-31. The audio itself is fetched straight from Instagram's CDN with no proxy at all, so the proxy only ever carries the page. Residential is not needed here and costs about forty times as much per byte.

## Actor input object example

```json
{
  "reelUrls": [
    "https://www.instagram.com/reel/DcozHIETCd9/",
    "DcMXl1IPNtB"
  ],
  "maxItems": 2,
  "maxDurationSeconds": 300,
  "skipPostsWithoutAudio": false,
  "skipLowConfidence": false,
  "speechConfidenceThreshold": "balanced",
  "language": "en",
  "translateToEnglish": false,
  "timestampGranularity": [
    "segment"
  ],
  "subtitleFormats": [
    "srt"
  ],
  "subtitleMaxCharsPerLine": 42,
  "textFormat": "continuous",
  "includeCaption": true,
  "includeEngagement": true,
  "includeCaptionEntities": true,
  "includeAltText": false,
  "includeTopics": false,
  "includeLocation": false,
  "includeMediaUrls": false,
  "includeOwnerProfile": false,
  "includeTaggedUsers": false,
  "includeCoauthors": false,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `transcripts` (type: `string`):

Every reel you asked for, one row each, including the ones that carried no audio.

# 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 = {
    "reelUrls": [
        "https://www.instagram.com/reel/DcozHIETCd9/",
        "DcMXl1IPNtB"
    ],
    "maxItems": 2,
    "maxDurationSeconds": 300
};

// Run the Actor and wait for it to finish
const run = await client.actor("shakamize/instagram-transcript-scraper").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 = {
    "reelUrls": [
        "https://www.instagram.com/reel/DcozHIETCd9/",
        "DcMXl1IPNtB",
    ],
    "maxItems": 2,
    "maxDurationSeconds": 300,
}

# Run the Actor and wait for it to finish
run = client.actor("shakamize/instagram-transcript-scraper").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 '{
  "reelUrls": [
    "https://www.instagram.com/reel/DcozHIETCd9/",
    "DcMXl1IPNtB"
  ],
  "maxItems": 2,
  "maxDurationSeconds": 300
}' |
apify call shakamize/instagram-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,shakamize/instagram-transcript-scraper"
        }
    }
}

```

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/Xm9cVpLEaB9lZiW6d/builds/3PheAaShp4shk0n0c/openapi.json
