Skip to content

Instantly share code, notes, and snippets.

@hexcowboy
Last active August 21, 2024 10:32
Show Gist options
  • Save hexcowboy/802853d960d79958500b1a587f3a7e51 to your computer and use it in GitHub Desktop.
Save hexcowboy/802853d960d79958500b1a587f3a7e51 to your computer and use it in GitHub Desktop.
Twitch Helix API - Get Video/VOD Offset and Comments from Clip ID

Since Twitch decomissioned API V5, there's no correct way to get the VOD offset for a clip. So I just inspected what the Twitch web app was doing and came up with a super cool hack.

I know this looks really complicated but really it just does two things. First it gets the clip information from the official API, then it uses Twitch GraphQL API to get the offset.

kimne78kx3ncx6brgo4mv6wki5h1ko is the Client ID that the Twitch web app uses. It can be used to access Twitch's GraphQL API (undocumented & not for public use). The postData variable contains a request and a sha256Hash. The sha256Hash is basically a job ID and may change in the future, but I added the current hash which should work for all clips as of posting this.

const clientId = "" // Put your Twitch Client ID here
const clientSecret = "" // Put your Twitch Client Secret here

// Generates a Twitch Bearer token from your Client ID and Secret
const {
    data: {
        access_token
    }
} = await axios.post(`https://id.twitch.tv/oauth2/token?client_id=${clientId}&client_secret=${clientSecret}&grant_type=client_credentials`)

// Gets the clip information from API Helix
const clipId = "CarefulRoundFloofSoonerLater-JShSibkZfWy2CjWR"
const {
    data: {
        data: [clip]
    }
} = await axios.get(`https://api.twitch.tv/helix/clips?id=${clipId}`, {
    headers: {
        "Authorization": `Bearer ${access_token}`,
        "Client-ID": clientId,
    }
})

// Gets the clip offset from Twitch GraphQL
const postData = [{
    "operationName": "ClipMetadata",
    "variables": {
        "channelLogin": clip.broadcaster_name,
        "clipSlug": clip.id
    },
    "extensions": {
        "persistedQuery": {
            "version": 1,
            "sha256Hash": "ab70572e66f164789c87936a8291fd15e29adc2cea0114b02e60f17d60d6d154"
        }
    }
}]
const {
    data: [{
        data: {
            clip: {
                videoOffsetSeconds
            }
        }
    }]
} = await axios.post("https://gql.twitch.tv/gql", postData, {
    headers: {
        "Client-ID": "kimne78kx3ncx6brgo4mv6wki5h1ko"
    }
})

console.log(videoOffsetSeconds)

Additionally you can now grab comments for the Twitch clip by using the offset and the kimne78kx3ncx6brgo4mv6wki5h1ko key.

const {
    data: comments
} = await axios.get(`https://api.twitch.tv/v5/videos/${clip.video_id}/comments?content_offset_seconds=${videoOffsetSeconds}`, {
    headers: {
        'Client-ID': 'kimne78kx3ncx6brgo4mv6wki5h1ko'
    }
})

console.log(comments)

Bonus: Limit comments to only the ones within the clip's duration

By default, the previously mentioned /comments endpoint returns all comments after the provided for the offset, and even some before the offset. You can filter the array by using the following snippet to only show comments that were posted during the clip.

// Get only the comments we need for the clip
const videoOffsetSecondsEnd = videoOffsetSeconds + Math.ceil(clip.duration)
const result = comments.filter(
    (comment) => comment.content_offset_seconds <= videoOffsetSecondsEnd && comment.content_offset_seconds >= videoOffsetSeconds
).sort(
    (comment) => comment.content_offset_seconds
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment