total gifs archived

how to use the api

all v2 routes mirror Tenor's own API, so you can usually just swap the base URL and remove the key. cors is set to allow any origin. to get a single GIF (in MP4 format, it's way more efficient), take the number off the end of any tenor.com/view link and put it after the slash.

GET /:id
MP4 for a Tenor post id. The .mp4 suffix is optional.
GET /v2/search?q=&limit=&pos=
titles and tags, terms ANDed, ordered by share count. pos is the cursor that came back as next. add contentfilter=high, medium or low to trim ratings. nothing is filtered by default.
GET /v2/posts?ids=
metadata for up to 50 ids at once, comma separated.
GET /v2/featured?limit=&pos=
GET /v2/random?q=
GET /v2/categories
GET /v2/autocomplete?q=
GET /v2/search_suggestions?q=
GET /v1/stats

ratelimit: 200 reqs / minute / IP

downloading dumps

the archive comes in two halves: the metadata, which is small enough to query on a laptop, and the media, which is about 7 TiB and lives in over 13,559 big files.

1. the metadata

one Parquet file per month of uploads, about 160 files and a few gigabytes in total. index.json lists every file with its size and row count.

https://bigdata.tiago.zip/dumps/index.json
https://bigdata.tiago.zip/dumps/2025-06/gifs.parquet

the parquets are relatively simple. a row is a gif, with all of the tenor metadata.

2. the media

all gifs are stored as mp4s in large blobs, called backs. three more columns on every row say where that GIF's bytes are: pack is which blob, pack_offset is where it starts and pack_length is how long it is. ask for exactly those bytes with a range request and you get the MP4 back.

import requests

row = ...  # one row from the parquet

start = row["pack_offset"]
end   = start + row["pack_length"] - 1

r = requests.get(f"https://bigdata.tiago.zip/packs/{row['pack']}.bin",
                 headers={"Range": f"bytes={start}-{end}"})
r.raise_for_status()
mp4 = r.content

note: sort your rows by pack and walk each blob once instead of firing random ranges across the whole set, and if you want most of a blob anyway, just download all of it. and a blob that has gone cold in storage needs a moment to wake up, so a 503 here means retry in a few seconds, not failure.

contact and removals: hi@tiago.zip