I’m a huge fan of Trakt, but I know people who are tempted by VIP solely for the widgets. Now that’s great, but those widgets probably aren’t worth your $5. If supporting websites is important to you, this is probably not the post for you. It’s likely that this method could break in the future, keep that in mind!

We’re going to use our server as a bit of a proxy.

Here’s a couple of examples of what we’ll be creating (they’re live).



Pretty slick huh? Let’s get yours up and running now!

First, ssh into your server. Now, let’s edit the nginx config.

sudo nano /etc/nginx/sites-available/default

Place the following above any other location blocks.

if ($request_uri ~* "/trakt/") {
    set $skip_cache 1;
location ~* ^/trakt/.*$ {
    rewrite ^ /wp-content/uploads/trakt/request.php?uri=$uri last;

Here we are creating a virtual directory “trakt” which is deferred to our php handler file.

Install the file once you’ve saved the changes.

sudo systemctl reload nginx

So, at the moment we are redirecting all requests to /trakt/… to our php file, let’s build that.

mkdir /var/www/html/wp-content/uploads/trakt
mkdir /var/www/html/wp-content/uploads/trakt/cache
mkdir /var/www/html/wp-content/uploads/trakt/cache/collected
mkdir /var/www/html/wp-content/uploads/trakt/cache/profile
mkdir /var/www/html/wp-content/uploads/trakt/cache/watched

Create a file in this folder called request.php

// Hardcode to avoid this server being exploited as a proxy
$user = '1e3820057d9da91d1b9b8cc6db3e8826';

// 60 minutes
$cachetime = 60 * 60;

$request = substr($_GET['uri'], strlen('/trakt/'));

// Some quick validation
$validation = explode('/', $request);
$valid = [
	'watched' => [

$cache = 'cache/' . $request;
$has_cache = file_exists($cache);

if (!isset($valid[$validation[0]]) || !in_array($validation[1], $valid[$validation[0]])) {
	header("HTTP/1.0 404 Not Found");

if (!$has_cache || time() - filemtime($cache) > $cachetime) {
	$url = 'https://widgets.trakt.tv/users/' . $user . '/' . $request;
	$filename = pathinfo(parse_url($url)['path'])['filename'];
	$stream = stream_context_create([
		'http' => [
			'method' => 'GET',
			'header' => 'Referer: https://trakt.tv/widgets/'
	copy($url, $cache, $stream);

header('Content-Type: ' . mime_content_type($cache));
header('Content-Length: ' . filesize($cache));

You’ll need to change the user variable to point to your id. You can extract this from the examples at this url:


This file accepts the request, runs a bit of validation (adjust as necessary), then proxy the request (with a bit of caching) with the referer header. Tricking the Trakt server to give us the correct image 

At current this doesn’t support the card type, but I’ve had moderate success with it. You would need to capture the card request and then cache each of the images too (cloudflare hotlinking protection) and replace those in the page.


You should probably sponsor Trakt if you like the system, alternatively – here you go!

There are currently no comments.