title: Scraping Instagram with PHP - Plugin Wordpress
body: <p>I'm trying to retreive the user's picture from Instagram without the access token. To do that, I build a scraper with PHP.
  It works quite well, but sometimes and only with some accounts, it doesn't work.</p>
  
  <p>Here the function to scrape Instagram:</p>
  
  <pre><code>function get_instagram_feed( $number, $username ) {
          error_reporting(0);
  
          require 'simple-cache.php';
          $cacheFolder = 'instagram-cache';
  
          $user = strtolower( $username );
          if (!file_exists($cacheFolder)) {
              mkdir($cacheFolder, 0777, true);
          }
          $cache = new Gilbitron\Util\SimpleCache();
          $cache-&gt;cache_path = $cacheFolder . '/';
          $cache-&gt;cache_time = 3600;
          $scraped_website = $cache-&gt;get_data("user-$user", "https://www.instagram.com/$user/");
          $document = new DOMDocument();
          libxml_use_internal_errors(true);
          $document-&gt;loadHTML($scraped_website);
          libxml_use_internal_errors(false);
          $selector = new DOMXPath($document);
          $anchors = $selector-&gt;query('/html/body//script');
  
          $images = array();
          $insta_feed = array();
  
          foreach($anchors as $a) {
              $text = $a-&gt;nodeValue;
              preg_match('/window._sharedData = \{(.*?)\};/', $text, $matches);
              $json = json_decode('{' . $matches[1] . '}', true);
              $images[] = $json['entry_data']['ProfilePage'][0]['graphql']['user']['edge_owner_to_timeline_media']['edges'];
          }
  
          for ( $i = 0; $i &lt; count($images); $i++ ) {
              $insta_feed[] = array(
                  'thumbnail' =&gt; $images[0][$i]['node']['thumbnail_resources'][0]['src'],
                  'small' =&gt; $images[0][$i]['node']['thumbnail_resources'][1]['src'],
                  'medium' =&gt; $images[0][$i]['node']['thumbnail_resources'][2]['src'],
                  'large' =&gt; $images[0][$i]['node']['thumbnail_resources'][4]['src'],
                  'original' =&gt; $images[0][$i]['node']['display_url'],
                  'link'  =&gt; trailingslashit( '//instagram.com/p/' . $images[0][$i]['node']['shortcode'] ),
                  'caption' =&gt; $images[0][$i]['node']['edge_media_to_caption']['edges'][0]['node']['text']
              );
          }
  
          if ( !empty( $insta_feed ) ) {
              return ( $number ) ? array_slice( $insta_feed, 0, $number ) : $insta_feed;
          }
      }
  </code></pre>
  
  <p>When it works, in the <code>foreach</code> I have <code>$a</code> is a <code>DOMElement Object</code> that I can navigate to get the images URLs.</p>
  
  <p>When it doesn't work, my <code>$a</code> looks like this:</p>
  
  <pre><code>DOMElement Object ( [tagName] =&gt; script [schemaTypeInfo] =&gt; [nodeName] =&gt; script [nodeValue] =&gt; (function(){ function normalizeError(err) { var errorInfo = err.error || {}; var getConfigProp = function(propName, defaultValueIfNotTruthy) { var propValue = window._sharedData &amp;&amp; window._sharedData[propName]; return propValue ? propValue : defaultValueIfNotTruthy; }; return { line: err.line || errorInfo.message || 0, column: err.column || 0, name: 'InitError', message: err.message || errorInfo.message || '', script: errorInfo.script || '', stack: errorInfo.stackTrace || errorInfo.stack || '', timestamp: Date.now(), ref: window.location.href, deployment_stage: getConfigProp('deployment_stage', ''), is_canary: getConfigProp('is_canary', false), rollout_hash: getConfigProp('rollout_hash', ''), is_prerelease: window.__PRERELEASE__ || false, bundle_variant: getConfigProp('bundle_variant', null), request_url: err.url || window.location.href, response_status_code: errorInfo.statusCode || 0 } } window.addEventListener('load', function(){ if (window.__bufferedErrors &amp;&amp; window.__bufferedErrors.length) { if (window.caches &amp;&amp; window.caches.keys &amp;&amp; window.caches.delete) { window.caches.keys().then(function(keys) { keys.forEach(function(key) { window.caches.delete(key) }) }) } window.__bufferedErrors.map(function(error) { return normalizeError(error) }).forEach(function(normalizedError) { var request = new XMLHttpRequest(); request.open('POST', '/client_error/', true); request.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); request.send(JSON.stringify(normalizedError)); }) } }) }()); [nodeType] =&gt; 1 [parentNode] =&gt; (object value omitted) [childNodes] =&gt; (object value omitted) [firstChild] =&gt; (object value omitted) [lastChild] =&gt; (object value omitted) [previousSibling] =&gt; (object value omitted) [nextSibling] =&gt; [attributes] =&gt; (object value omitted) [ownerDocument] =&gt; (object value omitted) [namespaceURI] =&gt; [prefix] =&gt; [localName] =&gt; script [baseURI] =&gt; [textContent] =&gt; (function(){ function normalizeError(err) { var errorInfo = err.error || {}; var getConfigProp = function(propName, defaultValueIfNotTruthy) { var propValue = window._sharedData &amp;&amp; window._sharedData[propName]; return propValue ? propValue : defaultValueIfNotTruthy; }; return { line: err.line || errorInfo.message || 0, column: err.column || 0, name: 'InitError', message: err.message || errorInfo.message || '', script: errorInfo.script || '', stack: errorInfo.stackTrace || errorInfo.stack || '', timestamp: Date.now(), ref: window.location.href, deployment_stage: getConfigProp('deployment_stage', ''), is_canary: getConfigProp('is_canary', false), rollout_hash: getConfigProp('rollout_hash', ''), is_prerelease: window.__PRERELEASE__ || false, bundle_variant: getConfigProp('bundle_variant', null), request_url: err.url || window.location.href, response_status_code: errorInfo.statusCode || 0 } } window.addEventListener('load', function(){ if (window.__bufferedErrors &amp;&amp; window.__bufferedErrors.length) { if (window.caches &amp;&amp; window.caches.keys &amp;&amp; window.caches.delete) { window.caches.keys().then(function(keys) { keys.forEach(function(key) { window.caches.delete(key) }) }) } window.__bufferedErrors.map(function(error) { return normalizeError(error) }).forEach(function(normalizedError) { var request = new XMLHttpRequest(); request.open('POST', '/client_error/', true); request.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); request.send(JSON.stringify(normalizedError)); }) } }) }()); )
  </code></pre>
  
  <p>I really can't understand. Form <code>localhost</code> it works always like a charm. On a live website and with some Accounts, I get this <code>DOMElement Object</code> without any interesting data.
  It happen mostly with the "verificated" accounts.</p>
  
  <p>Can somebody help me with this little challange?
  thx</p>