Decorative background for title

Stream and Competition Resources

Last updated: September 23, 2022

FF Logs offers a variety of resources and tools that can help enhance your livestream and competitions. Take a look at what we have available!

Guild Specific Widgets

The following stream widgets are available to each guild and can be used with a streaming software such as OBS. These can be found on the guild’s page on Warcraft Logs, in the Widgets tab.

These will update in real time as a guild progresses, refreshing every 30 seconds.

Progression Tiles

We have two available widgets for boss progression (horizontal and vertical), featuring guild and pull count information.

Encounter Summary Graphs

Multiple graphs are available help visualize pulls, precents, and progression time.

Composition and Gear

The following widgets contain composition, loot, and tier set information.

Latest Updates

Latest updates can be guild specific, or set to display activity from all of the top guilds.

General Competition Widgets

You will need custom URLs for these widgets. These stream widgets will update every 30 seconds, and will even update mid-fight to keep the most accurate boss percentage possible, letting guilds overtake each other mid-fight if they get a better percentage.

We can also provide embeds that expose certain details as text so you can style them however you like. Additionally, we can also easily build any custom widgets you need to fit your stream.


Our leaderboards are customizable using CSS. Here are some past customization examples.

Comparison Encounter Summary Graphs

Multiple graphs are available help visualize pulls, precents, and progression time.

Additional Resources

FF Logs offers some additional resources for your stream and competition.

Nightbot Support

We have support for a Nightbot Twitch command that viewers can use to get a quick recap of a guild's current progress. If you have Nightbot in your channel, you can add it with:

!commands add !best $(urlfetch<guild-id>

A guild id can be found at the end of the URL by visiting the guild on Warcraft Logs. Viewers can call best % info by typing !best in the chat.

We are able to easily create more Nightbot commands to fit different scenarios or requests.

Information Regarding API Data

If you want to get more up-close and personal with our API and start using it to build your own browser sources, here's a brief example of what such a .html file would look like.

let accessToken = null; getProgressRaceDataAndDoSomething(); async function getProgressRaceDataAndDoSomething() { const data = await getProgressRaceData(); document.getElementById('json-dump').innerHTML = JSON.stringify(data, null, 2); console.log(data); setTimeout(getProgressRaceDataAndDoSomething, 30000); } async function getProgressRaceData() { return await fetchJsonFromApi( `{ progressRaceData { progressRace(difficulty: 5) } }` ); } async function fetchJsonFromApi(query, variables = {}) { const accessToken = await getAccessToken(); const response = await fetch('', { method: 'POST', headers: { Authorization: 'Bearer ' + accessToken, 'Content-Type': 'application/json', }, body: JSON.stringify({ query, variables, }), }); const json = await response.json(); if (json.errors || ! setTimeout(() => window.location.reload(), 5000); return; } async function getAccessToken() { if (accessToken) return accessToken; const clientId = '95afcb80-4907-48ce-9b6b-63548759de18'; const clientSecret = 'xcOrUINWl12YPD53byR1S8OB3A0MivR51n2iZ7jr'; const authHeader = 'Basic ' + btoa(`${clientId}:${clientSecret}`); const response = await fetch('', { method: 'POST', headers: { Authorization: authHeader, 'Content-Type': 'application/x-www-form-urlencoded', }, body: 'grant_type=client_credentials', }); if (response.status === 200) { const json = await response.json(); accessToken = json.access_token; } else { setTimeout(() => window.location.reload(), 5000); } return accessToken; }

Everything after the first 10 or so lines is just GraphQL boilerplate, just defining a few functions so that all you need to do is const data = await getProgressRaceData(); and then get started working with that data. This example gets the data every 30 seconds and just dumps it out onto the page. On the off chance that an error occurs, it reloads the page so that it tries again. There's a huge amount of data in our API that you can access with different queries if you ever need to build anything else.

Contact Us

As always, we love to hear your feedback. Please join us on Discord to share any feedback and suggestions, or to ask any questions.

Follow our Twitter for updates!

If you have any support questions, please reach out to our support team at