The Discovery
Earlier in 2024 I had visited Japan, and while I didn't discover this website during my time there I had been really in love with Japan culture, it was something that really stayed with me even after I had gone back home, however shortly after returning home I discovered Misskey.io, a federated platform that's kind of like a self-hosted, community-driven version of Twitter.
It was pretty popular in Japanese artist circles, specifically those who wanted to sell commissions on other platforms such as Skeb.jp, which requires you to link either a X (Formally Twitter) or a Misskey.io account in order to access it. In a way it was the kind of place where you can find fanart, illustrations, and other creative posts that never make it to X, Pixiv, or even Skeb.
Now this is cool and all, but what's the important part of it? Well, after returning home and attempting to make an account, I discovered that this platform has locked users from making accounts if they're not located in Japan when they're making it. Even using a VPN would cause you to get errors, and while sure I could try to find a VPS in Japan, remote into it, and create an account for Misskey.io that way, it didn't seem like the most logical option, as I wanted a free way of just being able to see what type of posts were being made on there. You can technically browse user profiles publicly and even view the websites active timeline, but there’s a catch... Any post marked as “sensitive” won’t show its images unless you’re logged in.

At first, I thought that made sense... But as a developer, I couldn’t help but wonder - was that actually a server-side restriction… or just a frontend one?
Testing the Waters
Opening DevTools on a public profile revealed something interesting. Most images loaded perfectly fine and even in their highest quality. But when it came to those "sensitive" posts, instead of loading a blurred or censored preview, the site just… didn’t request the file at all. Sure it would try to load a "similar" color to the image for the page blur, but it never actually loaded an image.
The HTML for these hidden posts still contained a .image[data-id] element, but it looked like the frontend was intentionally skipping over rendering the real image. That instantly made me suspicious — if the element exists, there’s probably an API call that can reveal what’s behind it.
Sure enough, a bit of digging led me to an endpoint used by the site itself:
https:/api/notes/show
It took a simple JSON payload with a noteId and responded with full post data — including file URLs.
Even better: this endpoint didn’t require authentication, regardless of if an image was marked as sensitive or not.

Making the Bypass
With this discovery that technically the entire site can be viewed without being logged in, I decided to make a TamperMonkey userscript to automate the requests with a simple idea: Whenever a Misskey "note" is loaded without an image being included in an image container, it would submit a request for that notes details and fetch the real file URL using the notes ID.
Once the data was retrieved, it would replace the placeholder "fake blurred" image with the actual one, allowing me to click on it and open it in full quality.
Below is a snippet of the code that helped make this possible:
const API = location.origin + '/api/notes/show';
async function handleImageBox(imageBox: HTMLElement) {
const noteLink = imageBox.closest('article')?.querySelector('a[href*="/notes/"]');
if (!noteLink) return;
const noteId = noteLink.href.split('/notes/')[1].split(/[?#]/)[0];
const res = await fetch(API, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ noteId }),
});
const note = await res.json();
const file = note?.files?.find((f: any) => f.id === imageBox.dataset.id);
if (!file?.url) return;
const img = imageBox.querySelector('img');
if (img) img.src = file.url;
}
After setting up the above to grab the notes from the API, I added a fullscreen viewer that popped up when you clicked on any image so that I could easily view and browse art in a clean way without having each image open up a new tab with the image url everytime I wanted to see it without the cropping of the webpage. With more effort I could have auto-expanded the content of each note to match the size of the images, but I didn't want to deal with how that might be to mess with multiple images in a single upload.
Results & What This means
After setting up the Userscript, everything worked perfectly. Every image loaded even those marked as "Sensitive" content, and every image allowed me to view it in the highest quality that existed on Misskey's CDN.
I think the most interesting part about this journey was that this restriction wasn't due to any real access control or any API tokens, but instead due to the websites frontend just choosing not to show that content. At first I thought that this would've required some workaround to bypass API tokens but nope, it was purely a client-side visibility issue, and not a security mechanism.
Now to be fully clear here, this wasn't about accessing private or restricted content, i'm unsure of if private accounts are possible on Misskey.io, but I feel those would require more authentication if they did exist. This was simply about accessing already public data that was hidden to those who aren't logged into the website. You could still see the text of the post, but not the attached images. This can be seen as a good reminder that frontend-only "protections" aren't really protecting anything, because if someone like me wants to see that content and it's only protected on the frontend, we can find a way around it and view it unless it's gated by real access control systems.authentication
Still, it was a fun little exploration for what started as curiosity about a platform I saw in Japan turned into a quick script that peeled back some frontend layers and showed how easy it can be to misinterpret privacy for presentation.

