{"id":3271,"date":"2015-05-06T13:00:10","date_gmt":"2015-05-06T12:00:10","guid":{"rendered":"https:\/\/blog.ed.gs\/?p=3271"},"modified":"2015-05-06T13:00:10","modified_gmt":"2015-05-06T12:00:10","slug":"addremove-multiple-ips-to-cloudflares-blacklistwhitelist","status":"publish","type":"post","link":"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/","title":{"rendered":"Add\/Remove Multiple IPs to Cloudflare’s Blacklist\/Whitelist"},"content":{"rendered":"

I had a problem with Statuscake’s servers not being able to check my wp-login.php’s current up\/down status as it turns out that Cloudflare was challenging the visits from their servers to see if they were human or not. Cloudflare allows you to use their API to add and remove multiple IPs from your whitelist and blacklist in their admin dashboard. The following PHP code can be used, with modification of the configuration at the top, to allow this to happen in bulk, which they don’t allow you to do from their website. Run it via the php console command “php filenamehere.php” and it will output the current script status throughout.<\/p>\n

https:\/\/gist.github.com\/Coopeh\/931d5cb93587aa816bda553580bd8a56<\/a><\/p>\n

<?php $time_start = microtime(true);\n\n// Add multiple IPs to blacklist, whitelist or unlist them on Cloudflare using CloudFlare API by AzzA \n// Ed Cooper 2015 - https://blog.ed.gs\n// Version 1.0\n\n// Configure your API key and email address below\n\n$cfemailaddress = "your@email.com"; // Cloudflare email address\n$cfapikey = "1234123412341234123412341234"; // Cloudflare API key\n$type = "Whitelist"; // Use either Whitelist, Blacklist or Unlist as options\n\n// Use either $url, $ips or both, but make sure the URL address is a line break separated list of IPs, comment and uncomment the lines as needed\n\n$url = "https://www.statuscake.com/API/Locations/txt"; // Web address for line break separated list of IPs\n$ips = array("128.199.222.65","188.166.158.224","5.45.179.103","199.167.128.80","185.157.211.211","162.248.97.72","37.235.53.240","162.253.64.104","192.241.221.11","50.2.139.16","108.61.162.214","37.235.48.42","158.255.208.76","125.63.48.239","185.12.45.70","103.194.112.70","213.183.56.107","217.148.43.188","91.236.116.163","37.235.55.205","217.148.43.202","45.63.104.11","45.32.151.21","107.170.227.23","107.170.227.24","188.226.169.228","188.226.185.106","188.226.186.199","107.155.108.234","188.226.171.58","108.61.119.153","188.226.158.160","107.170.240.141","107.161.28.219","107.155.104.182","107.155.125.29","178.62.78.199","209.222.30.242","46.101.74.251","108.61.212.141","178.62.65.162","178.62.109.7","188.226.247.184","188.226.139.158","188.226.184.152","178.62.106.84","104.131.248.65","104.131.248.78","46.101.61.83","104.131.247.151","178.62.86.69","107.170.197.248","107.170.219.46","188.226.203.84","178.62.41.44","178.62.41.49","178.62.41.52","162.243.71.56","178.62.40.233","162.243.247.163","107.170.53.191","31.220.7.237","178.62.80.93","178.62.71.227","178.73.210.99","181.41.214.137","154.127.60.59","185.112.157.185","46.101.240.208","46.101.238.182","46.101.238.189","46.101.27.186","178.62.104.137","193.182.144.147","159.203.31.18","149.154.157.61","138.204.171.136","185.60.135.86","154.127.60.23","188.166.253.148","37.157.246.146","46.101.110.43","46.101.110.45","178.62.101.57","46.101.0.24","46.101.20.96","46.101.110.32","82.221.95.161","37.235.52.25","37.97.188.103","151.236.18.80","185.47.129.168","37.235.48.146","91.239.125.60","139.59.15.79","193.182.144.105","45.63.121.159","45.32.145.79","181.41.201.117","151.236.10.129","151.80.175.226","185.173.92.161","185.135.81.201","138.68.24.60","107.191.47.131","138.68.24.115","138.68.24.136","138.68.24.207","138.197.140.243","138.197.130.232","138.197.130.235","139.59.155.26","138.68.80.173","139.59.190.241","138.68.80.10","139.59.29.167","45.63.88.213","45.63.86.120","45.32.128.80","104.156.229.24","45.32.212.56","104.156.255.184","108.61.215.179","45.32.166.195","45.32.160.172","45.32.171.24","107.191.57.237","45.63.26.78","45.76.192.50","45.32.36.158","139.59.26.85","139.59.22.109","104.238.164.105","45.63.76.68","45.63.78.84","45.32.195.186","45.76.3.112","45.76.1.44","45.32.7.22","159.203.186.225","159.203.182.22","159.203.182.60","45.63.51.63","45.63.61.213","108.61.205.201","45.32.192.198","45.32.195.93","104.206.168.26","138.68.151.78","45.63.97.4","104.238.185.175","104.238.185.46","104.238.186.209","45.76.128.250","104.238.171.176","104.238.187.61","104.238.174.234","108.61.196.37","108.61.197.147","45.76.134.164","45.76.135.253","108.61.173.0","45.63.96.68","45.76.134.85","45.32.183.128","45.76.130.43","45.76.129.212","45.76.134.198","45.76.134.237","45.76.135.14","217.78.0.117","217.78.0.171","2a03:b0c0:1:a1::2d:6001","2001:19f0:7001:18cd:5400:00ff:fe03:86f7","2001:19f0:9002:18b:5400:00ff:fe46:338d","2001:19f0:6801:b6:5400:00ff:fe2d:9386","2a03:b0c0:0:1010::386:7001","2a03:b0c0:0:1010::39c:2001","2a03:b0c0:0:1010::539:9001","2001:19f0:5c01:1a9:5054:00ff:feb5:3dfd","2a03:b0c0:0:1010::385:4001","2604:a880:1:20::f64:c001","2a03:b0c0:1:d0::5e:f001","2001:19f0:7402:1ab:5054:00ff:fec5:d750","2a03:b0c0:1:d0::df:6001","2001:19f0:5801:20d:5054:00ff:fea5:ffcc","2a03:b0c0:1:d0::df:4001","2a03:b0c0:1:d0::df:b001","2a03:b0c0:0:1010::349:e001","2a03:b0c0:0:1010::3a5:1","2a03:b0c0:1:d0::df:3001","2604:a880:0:1010::d3d:a001","2a03:b0c0:1:d0::d0:3001","2604:a880:0:1010::56:6001","2a03:b0c0:1:d0::df:a001","2a03:b0c0:1:d0::5b:a001","2a03:b0c0:1:d0::5b:c001","2a03:b0c0:1:d0::5c:2001","2604:a880:0:1010::d32:6001","2604:a880:0:1010::d32:5001","2a03:b0c0:1:d0::2e5:1001","2a03:b0c0:1:d0::2e5:2001","2a03:b0c0:3:d0::173:b001","2a03:b0c0:3:d0::179:a001","2a03:b0c0:3:d0::179:b001","2a03:b0c0:1:d0::91:5001","2001:b60:1000:149:154:157:61:1","2a03:b0c0:3:d0::216:9001","2a03:b0c0:3:d0::216:a001","2a03:b0c0:1:d0::44f:1","2a03:b0c0:1:d0::1de:6001","2a03:b0c0:3:d0::b61:9001","2400:6180:100:d0::8e:e001","2a03:f80:972:193:182:144:105:1","2001:19f0:7001:76c:5400:00ff:fe2c:0bea","2001:19f0:6801:ba:5400:00ff:fe2e:556f","2001:19f0:ac01:1e2:5400:00ff:fe37:00e9","2001:19f0:ac01:195:5400:00ff:fe37:00ea","2001:19f0:ac01:1b7:5400:00ff:fe37:00eb","2001:19f0:ac01:1dc:5400:00ff:fe37:00ec","2001:19f0:5401:b8:5400:00ff:fe37:00fa","2001:19f0:5401:b6:5400:00ff:fe37:00fb","2001:19f0:5401:b7:5400:00ff:fe37:00fd","2001:19f0:9002:138:5400:00ff:fe37:02a1","2001:19f0:9002:17d:5400:00ff:fe37:02a2","2001:19f0:9002:17e:5400:00ff:fe37:02a3","2001:19f0:5801:20f:5400:00ff:fe37:027f","2001:19f0:5801:20e:5400:00ff:fe37:027e","2001:19f0:7001:18d6:5400:00ff:fe37:0412","2001:19f0:7001:18c4:5400:00ff:fe37:0413","2001:19f0:5c01:156:5400:00ff:fe37:080b","2001:19f0:5c01:163:5400:00ff:fe37:080c","2001:19f0:5c01:1a6:5400:00ff:fe37:080d","2001:19f0:6401:14a:5400:00ff:fe37:0870","2001:19f0:5:33f:5400:00ff:fe37:2d7b","2001:19f0:5:340:5400:00ff:fe37:2d7d","2001:19f0:5:342:5400:00ff:fe37:2d7f","2604:a880:400:d0::a27:6001","2604:a880:400:d0::a27:7001","2604:a880:400:d0::a27:8001","2001:19f0:6001:4ad:5400:00ff:fe37:2e33","2001:19f0:6001:27c:5400:00ff:fe37:2e79","2001:19f0:6401:12d:5400:00ff:fe37:2eb2","2001:19f0:6401:14c:5400:00ff:fe37:2eb7","2001:19f0:6401:93:5400:00ff:fe37:2eeb","2a03:b0c0:1:a1::821:b001","2001:19f0:7402:20f:5400:00ff:fe47:8333"); // Statuscake IPs\n\n// STOP EDITING NOW\n\nfunction get_data($url) {\n  $ch = curl_init();\n  $timeout = 5;\n  curl_setopt($ch, CURLOPT_URL, $url);\n  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);\n  $data = curl_exec($ch);\n  curl_close($ch);\n  return $data;\n}\n\nclass cloudflare_api\n{\n    // The URL of the API\n    private static $URL = array(\n        'USER' => 'https://www.cloudflare.com/api_json.html',\n        'HOST' => 'https://api.cloudflare.com/host-gw.html'\n    );\n\n    // Timeout for the API requests in seconds\n    const TIMEOUT = 5;\n\n    // Stores the api key\n    private $token_key;\n    private $host_key;\n\n    // Stores the email login\n    private $email;\n\n    /**\n     * Make a new instance of the API client\n     */\n    public function __construct()\n    {\n        $parameters = func_get_args();\n        switch (func_num_args()) {\n            case 1:\n                // a host API\n                $this->host_key  = $parameters[0];\n                break;\n            case 2:\n                // a user request\n                $this->email     = $parameters[0];\n                $this->token_key = $parameters[1];\n                break;\n        }\n    }\n\n    public function setEmail($email)\n    {\n        $this->email = $email;\n    }\n\n    public function setToken($token_key)\n    {\n        $this->token_key = $token_key;\n    }\n\n\n    /**\n     * CLIENT API\n     * Section 3\n     * Access\n     */\n\n    /**\n     * 4.7a - Whitelist IPs\n     * You can add an IP address to your whitelist.\n     */\n    public function wl($ip)\n    {\n        $data = array(\n            'a'   => 'wl',\n            'key' => $ip\n        );\n        return $this->http_post($data);\n    }\n\n    /**\n     * 4.7b - Blacklist IPs\n     * You can add an IP address to your blacklist.\n     */\n    public function ban($ip)\n    {\n        $data = array(\n            'a'   => 'ban',\n            'key' => $ip\n        );\n        return $this->http_post($data);\n    }\n\n    /**\n     * 4.7c - Unlist IPs\n     * You can remove an IP address from the whitelist and the blacklist.\n     */\n    public function nul($ip)\n    {\n        $data = array(\n            'a'   => 'nul',\n            'key' => $ip\n        );\n        return $this->http_post($data);\n    }\n\n    /**\n     * GLOBAL API CALL\n     * HTTP POST a specific task with the supplied data\n     */\n    private function http_post($data, $type = 'USER')\n    {\n        switch ($type) {\n            case 'USER':\n                $data['u']   = $this->email;\n                $data['tkn'] = $this->token_key;\n                break;\n            case 'HOST':\n                $data['host_key'] = $this->host_key;\n                break;\n        }\n        $ch = curl_init();\n        curl_setopt($ch, CURLOPT_VERBOSE, 0);\n        curl_setopt($ch, CURLOPT_FORBID_REUSE, true);\n        curl_setopt($ch, CURLOPT_URL, self::$URL[$type]);\n        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n        curl_setopt($ch, CURLOPT_POST, 1);\n        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);\n        curl_setopt($ch, CURLOPT_TIMEOUT, self::TIMEOUT);\n        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);\n        $http_result = curl_exec($ch);\n        $error       = curl_error($ch);\n        $http_code   = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n        curl_close($ch);\n        if ($http_code != 200) {\n            return array(\n                'error' => $error\n            );\n        } else {\n            $result = json_decode($http_result);\n            echo $result->{'response'}->{'result'}->{'ip'}." - ".ucfirst($result->{'result'})."\\n";\n        }\n    }\n}\n\n$valid = array();\n\n// Check if the URL is set in the parameters at the top then retrieve and validate the contents\nif (isset($url)) {\n    $url = get_data($url);\n\n    $comma = strpos($url, ",");\n    $space = strpos($url, " ");\n    $linebreak = strpos($url, "\\n");\n\n    if ($comma !== false) {\n        $url = explode(",", $url);\n        echo "Comma detected\\n";\n    } else if ($space !== false) {\n        $url = explode(" ", $url);\n        echo "Space detected\\n";\n    } else if ($linebreak !== false) {\n        $url = explode("\\n", $url);\n        echo "Line break detected\\n";\n    } else {\n        echo "Can't detect delimiter, is it a space, comma or new line?\\n";\n    }\n    if (is_array($url)) {\n        foreach ($url as $contents) {\n            if (filter_var($contents, FILTER_VALIDATE_IP)) {\n                array_push($valid, $contents);\n            } else {\n                echo $contents." is not valid.\\n";\n            }\n        }\n    }\n}\n\n// Check if any IPs are set in the parameters and validate the contents\nif (isset($ips)) {\n    if (is_array($ips)) {\n        foreach ($ips as $contents) {\n            if (filter_var($contents, FILTER_VALIDATE_IP)) {\n                array_push($valid, $contents);\n            } else {\n                echo $contents." is not valid.\\n";\n            }\n        }\n    }\n}\n\n// What have we got?\necho count($valid)." IPs detected. ".$type."ing with Cloudflare now...\\n";\n\n// Set the listing types\n$checkVars = array("Whitelist","Blacklist","Unlist");\n\n// Check the listing type and get started\nif(in_array($type, $checkVars)){\n\n    // Run the $url IPs first\n    if (isset($url)) {\n        if (is_array($url)) {\n            foreach ($url as $value) {\n                $cf = new cloudflare_api($cfemailaddress, $cfapikey);\n                if($type == "Whitelist") {\n                  $response = $cf->wl($value);\n                } elseif($type == "Blacklist") {\n                  $response = $cf->ban($value);\n                } elseif($type == "Unlist") {\n                  $response = $cf->nul($value);\n                }\n                print_r($response);\n            }\n        }\n    } else {\n        echo "No URL specified, trying IPs\\n";\n    }\n\n    // Run the $ips array second\n    if (isset($ips)) {\n        if (is_array($ips)) {\n            foreach ($ips as $value) {\n                $cf = new cloudflare_api($cfemailaddress, $cfapikey);\n                if($type == "Whitelist") {\n                  $response = $cf->wl($value);\n                } elseif($type == "Blacklist") {\n                  $response = $cf->ban($value);\n                } elseif($type == "Unlist") {\n                  $response = $cf->nul($value);\n                }\n                print_r($response);\n            }\n        }\n    } else {\n        echo "No manual IPs specified\\n";\n    }\n\n} else {\n    echo "Unknown type, please check configuration\\n";\n}\n\n// Fin\necho "Finished\\n";\n$time_end = microtime(true);\n\n$execution_time = ($time_end - $time_start);\n\necho "Script running time:".round($execution_time)." seconds\\n";<\/pre>\n","protected":false},"excerpt":{"rendered":"

I had a problem with Statuscake’s servers not being able to check my wp-login.php’s current up\/down status as it turns out that Cloudflare was challenging the visits from their servers to see if they were human or not. Cloudflare allows you to use their API to add and remove multiple IPs from your whitelist and […]<\/p>\n","protected":false},"author":2,"featured_media":3408,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ep_exclude_from_search":false},"categories":[16,28,51,60],"tags":[],"yoast_head":"\nAdd\/Remove Multiple IPs to Cloudflare's Blacklist\/Whitelist - E<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Add\/Remove Multiple IPs to Cloudflare's Blacklist\/Whitelist - E\" \/>\n<meta property=\"og:description\" content=\"I had a problem with Statuscake’s servers not being able to check my wp-login.php’s current up\/down status as it turns out that Cloudflare was challenging the visits from their servers to see if they were human or not. Cloudflare allows you to use their API to add and remove multiple IPs from your whitelist and […]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/\" \/>\n<meta property=\"og:site_name\" content=\"E\" \/>\n<meta property=\"article:published_time\" content=\"2015-05-06T12:00:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/static.ed.gs\/wp-content\/uploads\/2015\/05\/photo-1436377734980-0ee004df570b.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"2048\" \/>\n\t<meta property=\"og:image:height\" content=\"1265\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Ed\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ed\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/\",\"url\":\"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/\",\"name\":\"Add\/Remove Multiple IPs to Cloudflare's Blacklist\/Whitelist - E\",\"isPartOf\":{\"@id\":\"https:\/\/ed.gs\/#website\"},\"datePublished\":\"2015-05-06T12:00:10+00:00\",\"dateModified\":\"2015-05-06T12:00:10+00:00\",\"author\":{\"@id\":\"https:\/\/ed.gs\/#\/schema\/person\/d775615f2296ad0129fa3ea66346c628\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/\"]}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ed.gs\/#website\",\"url\":\"https:\/\/ed.gs\/\",\"name\":\"E\",\"description\":\"automation, consultancy, project management, web\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ed.gs\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/ed.gs\/#\/schema\/person\/d775615f2296ad0129fa3ea66346c628\",\"name\":\"Ed\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/ed.gs\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/4fe1dfaed09e6bdceb557d3008f5cc47?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/4fe1dfaed09e6bdceb557d3008f5cc47?s=96&d=mm&r=g\",\"caption\":\"Ed\"},\"url\":\"https:\/\/ed.gs\/author\/ed\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Add\/Remove Multiple IPs to Cloudflare's Blacklist\/Whitelist - E","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/","og_locale":"en_GB","og_type":"article","og_title":"Add\/Remove Multiple IPs to Cloudflare's Blacklist\/Whitelist - E","og_description":"I had a problem with Statuscake’s servers not being able to check my wp-login.php’s current up\/down status as it turns out that Cloudflare was challenging the visits from their servers to see if they were human or not. Cloudflare allows you to use their API to add and remove multiple IPs from your whitelist and […]","og_url":"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/","og_site_name":"E","article_published_time":"2015-05-06T12:00:10+00:00","og_image":[{"width":2048,"height":1265,"url":"https:\/\/static.ed.gs\/wp-content\/uploads\/2015\/05\/photo-1436377734980-0ee004df570b.jpeg","type":"image\/jpeg"}],"author":"Ed","twitter_misc":{"Written by":"Ed","Estimated reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/","url":"https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/","name":"Add\/Remove Multiple IPs to Cloudflare's Blacklist\/Whitelist - E","isPartOf":{"@id":"https:\/\/ed.gs\/#website"},"datePublished":"2015-05-06T12:00:10+00:00","dateModified":"2015-05-06T12:00:10+00:00","author":{"@id":"https:\/\/ed.gs\/#\/schema\/person\/d775615f2296ad0129fa3ea66346c628"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ed.gs\/2015\/05\/06\/addremove-multiple-ips-to-cloudflares-blacklistwhitelist\/"]}]},{"@type":"WebSite","@id":"https:\/\/ed.gs\/#website","url":"https:\/\/ed.gs\/","name":"E","description":"automation, consultancy, project management, web","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ed.gs\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-GB"},{"@type":"Person","@id":"https:\/\/ed.gs\/#\/schema\/person\/d775615f2296ad0129fa3ea66346c628","name":"Ed","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/ed.gs\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/4fe1dfaed09e6bdceb557d3008f5cc47?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4fe1dfaed09e6bdceb557d3008f5cc47?s=96&d=mm&r=g","caption":"Ed"},"url":"https:\/\/ed.gs\/author\/ed\/"}]}},"_links":{"self":[{"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/posts\/3271"}],"collection":[{"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/comments?post=3271"}],"version-history":[{"count":0,"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/posts\/3271\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/media\/3408"}],"wp:attachment":[{"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/media?parent=3271"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/categories?post=3271"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ed.gs\/wp-json\/wp\/v2\/tags?post=3271"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}