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

Tenor Compatibility API Guide

One URL change. Same integration. This guide is the primary entry point for clients migrating an existing Tenor integration to GIPHY's Tenor-compatible endpoints with minimal code changes.

In most cases you can be up and running by creating a GIPHY API key, swapping your API host from tenor.googleapis.com to api.giphy.com, and confirming your product follows GIPHY branding requirements.

Three-Step Migration

The sections below document supported endpoints, parameters, and a few compatibility differences.

This guide helps you migrate an existing Tenor client to GIPHY’s Tenor-compatible endpoints with minimal code changes. It is intended for clients that already know the Tenor API shape and want to send Tenor-style requests to GIPHY with minimal changes.


Important Compatibility Notes

Guarded Fields

Some response fields depend on API key capabilities.

FieldEndpointsWhen Returned
tags/v2/search, /v2/featured, /v2/postsOnly when the API key has tags access enabled

If a guarded field is not available for your API key, it is omitted from the response.

Sticker Filtering Limitations

searchfilter=sticker,static and searchfilter=sticker,-static are not supported. Use searchfilter=sticker only.

Client Key & Query Handling
  • Use the same client_key value across all API calls for a given integration.
  • Send the user's query exactly as typed, including punctuation and special characters.
Pagination

Pagination is supported on /v2/search and /v2/featured.

  • The response may include next.
  • Send that next value back as pos.
  • Treat pos as opaque.
  • /v2/posts does not return next.
Copy Code
curl "https://api.giphy.com/v2/search?q=cat&key=$API_KEY&limit=20"
curl "https://api.giphy.com/v2/search?q=cat&key=$API_KEY&limit=20&pos=$NEXT"
Content Filtering

contentfilter maps to the Motion Picture Association rating system:

  • off - G, PG, PG-13, R
  • low - G, PG, PG-13
  • medium - G, PG
  • high - G

Refer to GIPHY rating guide for more details

Renditions

media_filter supports the following rendition names:

Rendition NameNotes
previewSingle-frame GIF used for preloading.
gifFull GIF that loops automatically.
mediumgifReduced GIF, typically 2-5 MB.
tinygifSmall GIF, typically around 200px.
nanogifVery small GIF, typically around 100px.
mp4Full MP4 that plays once.
loopedmp4Looping MP4 with a 15s loop.
tinymp4Reduced MP4 optimized for mobile.
nanomp4Smallest MP4 for low bandwidth use.
webmSupported by the compatibility layer, but not a video format in the native guide.
webp_transparentFull quality WebP with transparency.
tinywebp_transparentAround 200px with transparency.
nanowebp_transparentAround 100px with transparency.
gif_transparentGIF with transparency layer.
tinygif_transparentSmall transparent GIF.
nanogif_transparentSmallest transparent GIF.
tinywebmNot currently supported.
nanowebmNot currently supported.
Register Share

/v2/registershare is not implemented as a direct compatibility endpoint. For share analytics, use the analytics URLs returned on each GIPHY item instead.

Analytics Mapping

  • The share equivalent of /v2/registershare is analytics.onsent.url.
  • GIPHY also supports analytics.onclick.url for click events.
  • GIPHY also supports analytics.onload.url for load events.

Fire these URLs client-side as GET requests and append random_id and ts for tracking.

Example Request
Copy Code
const gif = data.results[0];
const timestamp = Date.now();
// Share/send event equivalent for /v2/registershare
fetch(`${gif.analytics.onsent.url}?random_id=${random_id}&ts=${timestamp}`);
// Additional supported analytics events
fetch(`${gif.analytics.onclick.url}?random_id=${random_id}&ts=${timestamp}`);
fetch(`${gif.analytics.onload.url}?random_id=${random_id}&ts=${timestamp}`);

Endpoint Details

❗Parameters not listed in endpoint details are ignored.

Search Endpoint

Search for GIFs or stickers while keeping the Tenor-compatible request and response shape.

  • Responses include top-level results and optional next.
  • Use searchfilter=sticker for sticker content.
  • searchfilter=static, searchfilter=-static, ar_range, and random are not supported.

Gif URLSticker URL
api.giphy.com/v2/searchapi.giphy.com/v2/search?searchfilter=sticker
Request Parameters:Required:Example:Description:
key: stringYes$API_KEYGIPHY API key.
q: stringYescatSearch query.
client_key: stringNomy_appRecommended client identifier for your integration.
searchfilter: stringNostickerPartial support. sticker is supported. Default behavior returns GIF content.
country: stringNoUSRecommended country code. Default: US.
locale: stringNoen_USRecommended locale code. Default: en_US.
contentfilter: stringNomediumSupported values: off, low, medium, high. Default: off.
media_filter: stringNotinygif,mp4Partial support for mapped rendition names only.
limit: integerNo10Result count limit. Default: 20. Maximum: 50.
pos: stringNo$NEXTPagination cursor. Send the previous response next value back as pos.
ar_range: stringNoallIgnored
random: booleanNotrueIgnored
Successful Response (200 OK)
Example Request
Copy Code
curl "https://api.giphy.com/v2/search?q=cat&key=$API_KEY&client_key=my_app&limit=10&country=US&locale=en_US"
curl "https://api.giphy.com/v2/search?q=cat&key=$API_KEY&client_key=my_app&searchfilter=sticker&limit=10"
curl "https://api.giphy.com/v2/search?q=cat&key=$API_KEY&media_filter=gif,mp4,tinygif"

Featured Endpoint

Get featured or trending GIFs or stickers through the compatibility layer.

  • Responses include top-level results and optional next.
  • Use searchfilter=sticker for sticker content.
  • searchfilter=static, searchfilter=-static, and ar_range are not supported.

Gif URLSticker URL
api.giphy.com/v2/featuredapi.giphy.com/v2/featured?searchfilter=sticker
Request Parameters:Required:Example:Description:
key: stringYes$API_KEYGIPHY API key.
client_key: stringNomy_appRecommended client identifier for your integration.
searchfilter: stringNostickerPartial support. sticker is supported.
country: stringNoUSRecommended country code. Default: US.
locale: stringNoen_USRecommended locale code. Default: en_US.
contentfilter: stringNomediumSupported values: off, low, medium, high. Default: off.
media_filter: stringNotinygif,mp4Partial support for mapped rendition names only.
limit: integerNo10Result count limit. Default: 20. Maximum: 50.
pos: stringNo$NEXTPagination cursor. Send the previous response next value back as pos.
ar_range: stringNoallIgnored
Successful Response (200 OK)
Example Request
Copy Code
curl "https://api.giphy.com/v2/featured?key=$API_KEY&client_key=my_app&limit=10&country=US&locale=en_US"
curl "https://api.giphy.com/v2/featured?key=$API_KEY&searchfilter=sticker&limit=10"

Posts Endpoint

Fetch content by ID while preserving the Tenor-style response contract.

  • Responses include top-level results and do not include next.
  • This compatibility layer also accepts contentfilter on this route.

URL
api.giphy.com/v2/posts
Request Parameters:Required:Example:Description:
key: stringYes$API_KEYGIPHY API key.
ids: stringYesid1,id2,id3Comma-separated list of content IDs. Max 50 ids
client_key: stringNomy_appRecommended client identifier for your integration.
media_filter: stringNogif,mp4Partial support for mapped rendition names only.
Successful Response (200 OK)
Example Request
Copy Code
curl "https://api.giphy.com/v2/posts?key=$API_KEY&client_key=my_app&ids=id1,id2,id3"
curl "https://api.giphy.com/v2/posts?key=$API_KEY&ids=id1,id2,id3&media_filter=gif,mp4"

Categories Endpoint

Fetch category metadata in a Tenor-style format.

  • Responses include top-level tags.
  • Only featured and trending values are supported for type.

URL
api.giphy.com/v2/categories
Request Parameters:Required:Example:Description:
key: stringYes$API_KEYGIPHY API key.
client_key: stringNomy_appPreserved in generated category search URLs.
type: stringNofeaturedPartial support. featured and trending are supported.
contentfilter: stringNomediumAffects image visibility and generated URLs. Default: off.
Successful Response (200 OK)
Example Request
Copy Code
curl "https://api.giphy.com/v2/categories?key=$API_KEY&client_key=my_app&country=US&locale=en_US&type=featured&contentfilter=medium"

Autocomplete Endpoint

Get search autocomplete suggestions. Returns up to 20 terms.

  • Responses include top-level results.
  • Empty or missing q returns empty results.

URL
api.giphy.com/v2/autocomplete
Request Parameters:Required:Example:Description:
key: stringYes$API_KEYGIPHY API key.
q: stringYesexcAutocomplete query term.
client_key: stringNomy_appRecommended client identifier for your integration.
limit: integerNo10Suggestion count limit. Default: 20. Maximum: 50.
Successful Response (200 OK)
Example Request
Copy Code
curl "https://api.giphy.com/v2/autocomplete?key=$API_KEY&client_key=my_app&q=exc&limit=10&country=US&locale=en_US"

Search Suggestions Endpoint

Get related search terms. Returns up to 20 terms.

  • Responses include top-level results.
  • Empty or missing q returns empty results.

URL
api.giphy.com/v2/search_suggestions
Request Parameters:Required:Example:Description:
key: stringYes$API_KEYGIPHY API key.
q: stringYessmileRelated-term query term.
client_key: stringNomy_appRecommended client identifier for your integration.
Successful Response (200 OK)
Example Request
Copy Code
curl "https://api.giphy.com/v2/search_suggestions?key=$API_KEY&client_key=my_app&q=smile&limit=10&country=US&locale=en_US"

Trending Terms Endpoint

Get trending search terms. Returns up to 20 terms.

  • Responses include top-level results.
  • limit is not currently implemented on this compatibility route.

URL
api.giphy.com/v2/trending_terms
Request Parameters:Required:Example:Description:
key: stringYes$API_KEYGIPHY API key.
client_key: stringNomy_appRecommended client identifier for your integration.
Successful Response (200 OK)
Example Request
Copy Code
curl "https://api.giphy.com/v2/trending_terms?key=$API_KEY&client_key=my_app&country=US&locale=en_US"

Native GIPHY Experience Guide

The compatibility guide above is the fastest path for existing Tenor clients. Use the following migration guide to understand and implement a native GIPHY experience with direct /v1/* endpoints, native schema mapping, and deeper integration details.

WHEN TO USE THIS SECTION

Use this section when you want to move beyond the compatibility layer and adopt native GIPHY endpoints and response models.

The compatibility documentation above should take precedence for minimal-change migrations from Tenor.


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.

All API Keys start as beta keys, which are rate limited (100 searches/API calls per hour). If you need more than 100 API calls per hour you will need to submit an application to upgrade your API Key to production status via your dashboard. We will review your application and if you qualify, a member of our team will reach out via email to discuss pricing.

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_idcustomer_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 customer_id and ts (timestamp) parameters
IMPORTANT

The customer_id should be an identifier assigned to a user in your platform and kept consistent across that user's requests. If you do not have your own user ID, use the identifier returned by the Random ID Endpoint.

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
// Use your own stable user ID, or the value returned by GIPHY's Random ID endpoint
const customerId = getUserIdFromYourPlatform(); // or (await fetch('https://api.giphy.com/v1/randomid?api_key=YOUR_API_KEY').then((res) => res.json())).random_id
// Use this customer_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&customer_id=${customerId}`);
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}?customer_id=${customerId}&ts=${timestamp}`);
// When user clicks
fetch(`${gif.analytics.onclick.url}?customer_id=${customerId}&ts=${timestamp}`);
// When message is sent
fetch(`${gif.analytics.onsent.url}?customer_id=${customerId}&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_idcustomer_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 customer_id (your own stable user ID or the value returned by the Random ID 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