Reverse Engineering Google Slides | TheOpenPresenter
Login
Churches
vs ProPresenter
Pricing
Downloads
Connect to Screen
GitHub
All posts Reverse Engineering Google Slides<br>Embedding Google Slides is easy. Controlling it from another device, tracking every animation step, and keeping it working offline took a lot longer.
By Michael Salim on 4 August 2026 • 8 min read
code]:rounded [&_:not(pre)>code]:bg-gray-100 dark:[&_:not(pre)>code]:bg-gray-800 [&_:not(pre)>code]:px-1.5 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:text-[0.9em] [&_:not(pre)>code]:font-normal [&_:not(pre)>code]:text-gray-900 dark:[&_:not(pre)>code]:text-gray-100 prose-code:before:content-none prose-code:after:content-none prose-pre:rounded-lg prose-pre:border prose-pre:border-gray-200 dark:prose-pre:border-gray-800 prose-hr:border-gray-200 dark:prose-hr:border-gray-800 prose-th:text-gray-900 dark:prose-th:text-gray-100 prose-td:text-gray-600 dark:prose-td:text-gray-300 mb-16"> I’m a big fan of Google Slides. As someone who often helps out with multimedia at events, I much prefer receiving Google Slides over a PowerPoint file. This is for two main reasons. For one, it’s so much easier to collaborate with. The other side can update the slides at any time without a back and forth. Secondly, I use Linux, so opening a PowerPoint file often leads to style issues, usually from missing fonts.
So when building TheOpenPresenter, support for Google Slides was one of the first things that came to mind.
The requirements are simple:
I should be able to import the slides easily
I should be able to control the slides remotely
And oh man, I can tell you that it was an iterative process.
The easy way out: export to PDF
Most integrations with slides software simply export a PDF file. This is nice because you won’t get any issues with styles. Google Slides also has an API to do this.
The obvious downside is that it will be a static image. Personally that’s fine for me. But try telling that to people who just want their slides to work :)
As far as I can tell, nobody has done an integration that allows something like this before.
Part 1: Controlling an embed remotely
The obvious starting point is looking at embedding Google Slides directly into the software. They do provide a URL for this. Great!
Now the harder question: how do I control it programmatically without having direct access to the embed? This is the main essence of this article.
Going to the next and previous slides was easy enough. All I needed to do was simulate the left and right arrow.
iframeRef.current?.contentDocument?.dispatchEvent(<br>new KeyboardEvent("keydown", { key: "ArrowRight", keyCode: 39 }),<br>);<br>But how about jumping to different slides? I could spam the arrows, but that doesn’t seem reliable.
Experimenting with different URL parameters
The first thing I did was look through the source code to see if there’s a function I can call. The first thing I noticed is that there are a few flags you can pass to the embed URL that put it into different modes.
They didn’t end up being all that useful. I did however find that the slides are anchored, meaning I can pass #slide3 at the end of the URL to navigate to different slides. However, after a bit of testing, that method wasn’t too reliable due to a bug in WebKit.
Changing slides through embed UI
Another lead was this navigation button. If I can find the function that leads there, I can simply call that function. Given that it’s public, of course. But after diving deep into the code, my hopes were slowly fading. Remember, this is obfuscated code, so it’s not an easy task to understand what’s actually happening.
Using keyboard shortcuts instead
After sitting on it for a few days, I noticed that Google Slides has some keyboard shortcuts. Particularly, there is a shortcut to jump to a specific slide!
And sure enough, that worked. So going to a specific slide is as simple as:
slideIWantToGoTo<br>.toString()<br>.split("")<br>.map((x) => keyCodeMapping[x])<br>.forEach((keyCode) => {<br>iframeRef.current?.contentDocument?.dispatchEvent(<br>new KeyboardEvent("keydown", { keyCode }),<br>);<br>});<br>iframeRef.current?.contentDocument?.dispatchEvent(<br>new KeyboardEvent("keydown", { key: "Enter", keyCode: 13 }),<br>);<br>Part 2: Accessing the data
At this point I can move the slides around. But there’s still a lot of hooking up to do.
I don’t know how many slides there are. I don’t know which slides have animations, or how many clicks each one needs. I don’t know how long a transition takes. Without that, the remote is just a pair of arrow buttons firing blindly into a black box.
So where does that data live?
Turns out it’s all sitting right there in the HTML document of the embed. There’s a big JSON blob in there with everything I need. Great news!
The bad news is that it’s completely undocumented, and it’s not a nice object with keys to tell me what it is. It’s arrays upon arrays upon arrays. There’s nothing to tell you what index 7 is supposed to...