How to Build a Draft Sync Tool

I've got sync working for Yahoo and ESPN. What have I learned so far?

First off, I suspect that it's a dumb idea to write this post. I feel like I've figured out something that no one else knows, and I'm not sure it's in my best interests to give that to potential competitors.

For some reason, though, I just want to share it. Maybe it's pride, maybe it's just my generous spirit. Or maybe I'm just no good at keeping secrets.

Anyway, let's talk about how everyone else does sync, and what I think is a better way.

Other sync tools

One of the nice things about a Chrome extension is that it's code that is all downloaded and then run on your computer. It's just JavaScript, which means it's not compiled and (usually) easy to read.

So I've looked at how other people do sync.

Official API

Some sites...well, Yahoo, at least...has a public API that you can use. It's old, from the days when XML was the data protocol of choice, but it's still here. You don't even need a Chrome extension to access it.

I never dug too deep into this option... What's the point if you've got to use other methods for every other site? I think it could be more useful for in-season: It lets you set your lineups from a third party tool. But I'm not sure if draft data is populated here in real-time.

Unofficial API

For non-Yahoo sites, you can try to use their unofficial APIs. In this case, you do need a Chrome extension. In order to authenticate on the site, you need to read a user's cookies, and an extension is the smoothest way to do that.

Once again, this is a better option for in-season tools than in-draft ones. The API is used for league pages, and sometimes those don't get updated in the middle of the draft.

HTML Scraping

For draft tools that need real-time data, the normal thing to do is to scrape data off of the HTML elements on the draft page using a Chrome extension.

This has some problems. First of all, the data is scattered all over the place. You have to pull the league name from the heading, the team names from somewhere else, and the draft picks from another spot.

And those draft picks are the especially tricky part. Yahoo and ESPN both keep a log of picks on the main page, which is the most tempting spot to scrape. But if the user leaves the draft (intentionally or accidentally) that data is gone forever. You need the user to navigate to the draft board to fill in those lost picks, and then you have to merge new picks from the log into that.

My Approaches

Knowing that limitation from other tools, I wasn't convinced that surface-level scraping was the best way to go. So I kept digging in the Chrome Developer Tools and found something interesting.

Extracting React state

Both Yahoo and ESPN use React for their draft room. If you're not familiar with it, React is a framework from Facebook that lets you build a webpage that is easy to update without refreshing the page (like Facebook's timeline feed).

To handle updates, the page needs to keep track of its state. You can see how that makes sense in a draft room: The players section can automatically remove players if it knows who has been drafted. The roster section can put those drafted players into your lineup slots. React keeps track of the state of the draft

For Yahoo and ESPN's React-powered draft rooms, if you dig around in the properties of the DOM elements, you can find ones that contain all of the data you need: the league settings, the scoring categories, the positions, all the team info, all the draft picks, and all the player data.

Then, your Chrome extension isn't just looking at the surface data, it's reading the underlying data all from one place. You don't have to worry about leaving the draft room or having the right items displayed on the screen. You just pull everything every couple of seconds when you sync.

I won't go into the full details here, but here are the basics of how I got it working:

I'm not positive all of that is necessary. I couldn't find much info about this, and it took me a lot of trial and error to get it working.

Other sites and approaches

I've decided that after Yahoo and ESPN, my two syncing targets are Sleeper (for football) and Fantrax (for baseball). I'm pretty content to ignore the rest.

I haven't figured out how to crack either of those open (yet). Fantrax uses Angular instead of React, and I don't know how Angular tracks state. Sleeper has some React, but maybe it's Phoenix Liveview that handles populating data?

Both Sleeper and Fantrax put the draft board front and center in the draft room. If you're scraping the HTML, that makes the picks much easier to deal with than on Yahoo and ESPN. However, I don't see an obvious way to get the scoring categories via scrape.

It looks like Sleeper has a public API that is up-to-date. You can get the draft_id from the URL and plug it in:

const response = await fetch("https://sleeper.com/graphql", {
  "headers": {
    "accept": "application/json",
    "accept-language": "",
    "content-type": "application/json"
  },
  "body": "{\"operationName\":\"get_draft\",\"variables\":{},\"query\":\"query get_draft {\\n        get_draft(sport: \\\"nfl\\\",draft_id: \\\"1111111111111111111\\\"){\\n          created\\n          creators\\n          draft_id\\n          draft_order\\n          last_message_time\\n          last_message_id\\n          last_picked\\n          league_id\\n          metadata\\n          season\\n          season_type\\n          settings\\n          sport\\n          status\\n          start_time\\n          type\\n        }\\n\\n        user_drafts_by_draft(draft_id: \\\"1111111111111111111\\\"){\\n          user_id\\n          user_display_name\\n          user_avatar\\n          user_is_bot\\n          metadata\\n        }\\n\\n        \\n        draft_picks(draft_id: \\\"1111111111111111111\\\") {\\n          draft_id\\n          pick_no\\n          player_id\\n          picked_by\\n          is_keeper\\n          metadata\\n          reactions\\n        }\\n      \\n      }\"}",
  "method": "POST"
});

const data = await response.json();

If you can fetch data from that endpoint, you don't even need a Chrome extension. So maybe Sleeper will be the easiest nut to crack.

DraftKick Baseball is available now!

If you're still tracking your draft with a custom spreadsheet or even just pen and paper, you need to try DraftKick.

It is packed with features to help you succeed on draft day:

It's completely free to try out!

Hi,

I'm Mays. I've been playing fantasy since I was in high school (over two decades ago).

My speciality has always been player valuation—converting player stats into rankings and salary values. VBD for fantasy football? Rotisserie z-scores? We go way back. In 2009, I started Last Player Picked, a site that generated fantasy values customized for your league.

You can find me on Twitter at @MaysCopeland or email me at [email protected].