GAPI

Response shape

One object, the same every time. A field that does not apply comes back as null rather than disappearing, so your parser never has to check whether a key exists.

Top level

FieldTypeNotes
platformstringWhich network the link belonged to: instagram, youtube, tiktok, facebook, vk, threads, twitter, reddit or pinterest
typestringvideo, image, album, or audio when you asked YouTube for mp3
titlestring | nullThe caption, or the video's title, when the post carries one
authorstring | nullAccount or channel name, where the platform reports it
thumbnailstring | nullPreview image
durationnumber | nullLength in seconds, where the platform reports it
mediaarrayAlways present, always at least one item

Inside media

FieldTypeNotes
typestringvideo, image or audio
urlstringDirect link to one file. A video arrives with its audio already in it, so there is nothing to join afterwards.
qualitystring | nullThe height VK encoded this rendition at, as a label like 1080p, or the format you asked YouTube for. null everywhere else.
extstring | nullmp4 or mp3 where the platform states it, null where it does not

What is always filled in

platform, type and media always carry something. The other four do not: the same platform can answer with an author on one link and null on the next, so treat all four as optional and nothing will surprise you.

The one endpoint with a different shape

/v2/youtube/info downloads nothing, so it has nothing to put in media. It answers with the video's own facts instead: an id, an author_url, every thumbnail size, and a formats array listing each quality with its size in bytes. That body is on the YouTube page.

Writing against it

data = response.json()

if data["type"] == "album":
    print(len(data["media"]), "files")

for item in data["media"]:
    download(item["url"])