GIPHY Alt Text for GIFs is now available! Email us to learn more at bd.team@giphy.com.
GIPHY Clips (GIFs with Sound)have arrived! Learn about adding Clips to your app in our documentation!
Need to move your project from Tenor to GIPHY?   Check out our  migration guide!
logo

Migrating from Tenor to GIPHY API

This guide provides comprehensive information for developers migrating from the Tenor API to the GIPHY API. While both APIs provide access to GIF and sticker content, there are important differences in endpoints, parameters, response structures, and features.

🚀 Consider Using the GIPHY SDK

Want a faster, easier integration? Check out our official GIPHY SDKs for JavaScript, iOS, and Android. The SDK handles pagination, analytics tracking, and rendition optimization automatically, letting you focus on building great experiences instead of managing API details.

IMPORTANT

API keys from Tenor will not work with GIPHY.

You must create a new API key in the GIPHY Developer Dashboard.

Plan for testing time as pagination and analytics tracking work differently.


Authentication

Authentication differs between Tenor and GIPHY:

Before (Tenor)
Copy Code
curl "https://tenor.googleapis.com/v2/search?q=excited&key=YOUR_TENOR_KEY"
After (GIPHY)
Copy Code
curl "https://api.giphy.com/v1/gifs/search?q=excited&api_key=YOUR_GIPHY_KEY"
Try in API Explorer →

Base URL

PlatformBase URL
Tenorhttps://tenor.googleapis.com
GIPHYhttps://api.giphy.com

Endpoint Mappings

Below is a comprehensive mapping of Tenor endpoints to their GIPHY equivalents:

Search GIFs

TenorGIPHYNotes
/v2/search/v1/gifs/searchSee pagination differences below
Try GIF Search in API Explorer →

Search Stickers

TenorGIPHYNotes
/v2/search?searchfilter=sticker/v1/stickers/searchUses URL slug instead of query parameter
Key Difference: GIPHY excludes low-contrast stickers if remove_low_contrast=true

Trending / Featured

TenorGIPHY
/v2/featured/v1/gifs/trending
/v2/featured?searchfilter=sticker/v1/stickers/trending
Try Trending in API Explorer →

Categories

TenorGIPHYNotes
/v2/categories/v1/gifs/categoriesGIPHY provides the category's featured GIF

Autocomplete

TenorGIPHY
/v2/autocomplete/v1/gifs/search/tags

Both require q parameter. Optional pagination parameters supported.

Search Suggestions

TenorGIPHY
/v2/search_suggestions (uses q)/v1/tags/related/<term>

Trending Search Terms

TenorGIPHY
/v2/trending_terms/v1/trending/searches

Fetch by IDs

TenorGIPHYNotes
/v2/posts?ids=<ids>/v1/gifs?ids=<ids>Both use comma-separated list
/v1/gifs/:idGIPHY also offers single-ID endpoint

Random

TenorGIPHY
/v2/search?random=true/v1/gifs/random
/v2/search?random=true&searchfilter=sticker/v1/stickers/random
KEY DIFFERENCE

Tenor returns a list of random results.

GIPHY returns a single random item.

Try Random in API Explorer →

Random ID

TenorGIPHY
/v2/anonid/v1/randomid

Parameter Changes

Pagination

CRITICAL CHANGE

Tenor uses a token-based pagination system with pos and next values.

GIPHY uses a simple numeric offset model with offset and limit.

Unlike Tenor, which uses opaque cursor tokens, GIPHY uses a simple numeric offset representing how many results to skip.

  • offset=25 returns results starting from the 26th item
  • Calculate subsequent pages by incrementing the offset by your limit parameter
  • GIPHY responses do not include a next cursor
  • Pagination state is entirely controlled by request parameters
Before (Tenor)
Copy Code
// First page
const response1 = await fetch('https://tenor.googleapis.com/v2/search?q=cats&key=KEY');
const data1 = await response1.json();
// Next page using token
const response2 = await fetch(`https://tenor.googleapis.com/v2/search?q=cats&key=KEY&pos=${data1.next}`);
After (GIPHY)
Copy Code
// First page
const response1 = await fetch('https://api.giphy.com/v1/gifs/search?q=cats&api_key=KEY&limit=25&offset=0');
const data1 = await response1.json();
// Next page using numeric offset
const response2 = await fetch('https://api.giphy.com/v1/gifs/search?q=cats&api_key=KEY&limit=25&offset=25');

Content Safety / Rating

Tenor ParameterGIPHY ParameterValues
contentfilterratingTenor: off | low | medium | high
GIPHY: r | pg-13 | pg | g

GIPHY defaults to r (restricted). Default and maximum rating can be configured for partners.

User Identifier

TenorGIPHYNotes
anon_idrandom_idCan be supplied in every GIPHY request

Renditions / Media Formats

TenorGIPHY
media_filter (basic | minimal)bundle (clips_grid_picker | messaging_non_clips | sticker_layering | low_bandwidth)
OR
fields parameter for fields on demand

Example: fields=images.original.url,slug

Locale

TenorGIPHY
locale (xx_YY or YY)lang + country_code

Proxied Requests

GIPHY allows proxying user requests with:

  • country_code
  • region_code

Similarities

The following parameters work the same way in both APIs:

  • q - Search term(s)

Analytics & Tracking

MAJOR CHANGE

Tenor centralizes tracking through /v2/registershare endpoint.

GIPHY decentralizes tracking with per-item analytics URLs.

Tenor: Register Share

Tenor uses a dedicated endpoint /v2/registershare where your backend logs share events directly.

GIPHY: Analytics Object

Each GIPHY item includes an analytics object with event-specific URLs:

  • analytics.onload.url - Fire when item loads
  • analytics.onclick.url - Fire when user clicks
  • analytics.onsent.url - Fire when message is sent

To register interactions:

  • Fire URLs client-side (GET request)
  • Append random_id and ts (timestamp) parameters
IMPORTANT

The random_id should be obtained from the /v1/randomid endpoint and used consistently for that user across all API requests and analytics tracking.

Before (Tenor)
Copy Code
// Log share event to backend
await fetch('https://tenor.googleapis.com/v2/registershare', {
method: 'POST',
body: JSON.stringify({
id: gifId,
key: API_KEY,
q: searchTerm
})
});
After (GIPHY)
Copy Code
// Get random_id from GIPHY (once per user, store for future use)
const randomIdResponse = await fetch('https://api.giphy.com/v1/randomid?api_key=YOUR_API_KEY');
const { random_id } = await randomIdResponse.json();
// Use this random_id for all API requests and analytics for this user
const searchResponse = await fetch(`https://api.giphy.com/v1/gifs/search?q=cats&api_key=YOUR_API_KEY&random_id=${random_id}`);
const data = await searchResponse.json();
// Fire analytics URLs client-side
const gif = data.data[0];
const timestamp = Date.now();
// When GIF loads
fetch(`${gif.analytics.onload.url}?random_id=${random_id}&ts=${timestamp}`);
// When user clicks
fetch(`${gif.analytics.onclick.url}?random_id=${random_id}&ts=${timestamp}`);
// When message is sent
fetch(`${gif.analytics.onsent.url}?random_id=${random_id}&ts=${timestamp}`);

Response Schema

Response Body and Status

PlatformResponse Structure
Tenor• Uses standard HTTP status codes
• Known errors return HTTP 200 with error field
• Unknown errors use non-200 codes
GIPHY• All responses include meta object
• meta contains: status, msg, response_id
• Errors indicated via meta.status
• Some errors return empty data with 4xx status
SYNTHETIC ERROR CASE

If meta.status=200, meta.response_id="" and body is empty, treat as an error.

Always validate data presence in GIPHY responses.

Pagination Results

TenorGIPHY
results, nextdata, pagination, meta

Tenor uses next token; GIPHY uses offset + limit in the pagination object.

Tenor Response
Copy Code
{
"results": [...],
"next": "CAgQABokCOWW3Y8GMgYIChCAgBASJAj6z96PBjIGCAoQgJAQEiQIqqDejwYyBggKEIDgHA"
}
GIPHY Response
Copy Code
{
"data": [...],
"pagination": {
"total_count": 50000,
"count": 25,
"offset": 0
},
"meta": {
"status": 200,
"msg": "OK",
"response_id": "abc123def456"
}
}

HTTP Status Codes

CodeTenor DescriptionGIPHY DescriptionMigration Notes
200OK or known errorOK; check metaValidate data presence
3xxRedirect (rare)Not documentedIgnore or handle normally
400Not documentedBad requestValidate params
401Not documentedUnauthorizedVerify API key
403Not documentedForbiddenEnsure permissions
404Not foundNot foundShow user-friendly message
414Not documentedURI too longTrim queries
429Rate limit exceededToo many requests100 requests/hour beta limit
5xxServer errorSynthetic 200Retry with backoff

GIF / Sticker Object Field Mappings

Core Fields

Tenor FieldGIPHY EquivalentNotes
ididString ID
titletitle
content_descriptiontitle / alt_textIf available
media_formatsimagesRemap renditions (see below)
createdcreate_datetime / update_datetime / import_datetime / trending_datetimeUnix timestamp → ISO 8601
tagstags / featured_tags / user_tagsPartner-only

Additional Fields

TenorGIPHYNotes
content_ratingrating
urlurlAlso: embed_url, source_post_url
itemurlbitly_urlShareable short URL
hasaudioNo equivalent
hascaptionNo equivalent
flagsis_sticker / is_low_contrastBoolean flags

GIPHY user data includes username and public user info when available.


Rendition Mapping Guide

RECOMMENDATION

Use MP4 and WEBP formats where supported to maximize quality and reduce load time.

GIPHY provides more rendition options than Tenor for better optimization.

GIF & Video Renditions

Tenor FormatTypical UseGIPHY EquivalentNotes
previewSingle-frame GIFpreview_gif / fixed_*_stillPreloading
gifFull GIForiginalLoops automatically
mediumgifReduced GIFdownsized / downsized_medium2–5 MB
tinygifSmall GIFfixed_width / fixed_height~200px
nanogifVery small GIFfixed_*_small~100px
mp4Full MP4original.mp4 / hd.mp4 / 4k.mp4Plays once
loopedmp4Looping MP4looping.mp415s loop
tinymp4Reduced MP4fixed_*.mp4Mobile optimized
nanomp4Smallest MP4fixed_*_small.mp4 / preview.mp4Low bandwidth
webmVideooriginal.webp (animated)Not a video format

Transparent Sticker Renditions

Tenor FormatGIPHY EquivalentNotes
webp_transparentoriginal.webpFull quality WebP with transparency
tinywebp_transparentfixed_width.webp / fixed_height.webp~200px with transparency
nanowebp_transparentfixed_*_small.webp~100px with transparency
gif_transparentoriginal.gif (stickers)GIF with transparency layer
tinygif_transparentfixed_width.gif / fixed_height.gifSmall transparent GIF
nanogif_transparentfixed_*_small.gifSmallest transparent GIF
Accessing Renditions
Copy Code
// GIPHY response structure
const gif = data.data[0];
// Original (highest quality)
const originalUrl = gif.images.original.url;
const originalMp4 = gif.images.original.mp4;
// Fixed width (responsive)
const fixedWidth = gif.images.fixed_width.url;
const fixedWidthMp4 = gif.images.fixed_width.mp4;
// Downsized (optimized)
const downsized = gif.images.downsized.url;
// Preview (still frame)
const previewGif = gif.images.preview_gif.url;
// For stickers with transparency
const stickerWebp = gif.images.original.webp;

Migration Checklist

Follow this checklist to ensure a smooth migration from Tenor to GIPHY:

1. Authentication & Setup

  • ☐ Create a new API key in the GIPHY Developer Dashboard
  • ☐ Update base URL from tenor.googleapis.com to api.giphy.com
  • ☐ Replace key parameter with api_key in all requests

2. Update Endpoints

  • ☐ Map search endpoints: /v2/search/v1/gifs/search
  • ☐ Update sticker searches: use /v1/stickers/search instead of searchfilter param
  • ☐ Map trending: /v2/featured/v1/gifs/trending
  • ☐ Update autocomplete: /v2/autocomplete/v1/gifs/search/tags
  • ☐ Map random: /v2/search?random=true/v1/gifs/random
  • ☐ Update ID fetching: /v2/posts/v1/gifs

3. Modify Request Parameters

  • ☐ Replace pagination: pos token → offset numeric value
  • ☐ Update content filtering: contentfilterrating
  • ☐ Change user ID: anon_idrandom_id
  • ☐ Update locale: localelang + country_code
  • ☐ Modify rendition requests: media_filterbundle or fields

4. Update Response Parsing

  • ☐ Change array access: resultsdata
  • ☐ Add meta object validation
  • ☐ Handle synthetic error cases (empty body with status 200)
  • ☐ Update pagination logic (no more next token)
  • ☐ Map object fields: media_formatsimages
  • ☐ Update timestamp parsing: Unix → ISO 8601

5. Implement Analytics Tracking

  • ☐ Remove /v2/registershare backend calls
  • ☐ Implement client-side analytics URL firing
  • ☐ Fire analytics.onload.url when GIF loads
  • ☐ Fire analytics.onclick.url when user clicks
  • ☐ Fire analytics.onsent.url when message sent
  • ☐ Append random_id (from /v1/randomid endpoint) and ts to analytics URLs

6. Update Rendition Logic

  • ☐ Map Tenor renditions to GIPHY equivalents
  • ☐ Prefer MP4 formats for better performance
  • ☐ Use WebP for stickers with transparency
  • ☐ Update preview/still frame logic
  • ☐ Handle random endpoint difference (list → single item)

7. Testing & Validation

  • ☐ Test all migrated endpoints with the API Explorer
  • ☐ Verify pagination works correctly with numeric offsets
  • ☐ Confirm analytics tracking fires properly
  • ☐ Test error handling for synthetic 200 errors
  • ☐ Validate renditions display correctly
  • ☐ Check rate limiting (100 requests/hour for beta keys)
  • ☐ Test with different rating values

8. Production Deployment

  • ☐ Update production API keys
  • ☐ Monitor error rates and response times
  • ☐ Set up alerts for rate limit warnings
  • ☐ Document any partner-specific configurations
  • ☐ Update API documentation for your integration