Fix Instagram and Facebook Media Fetch

How to fix Instagram's 'media could not be fetched from this URI', 'only photo or video accepted', and Facebook's 403 robots.txt errors.

Fix Instagram and Facebook Media Fetch

If you publish to Instagram or Facebook through an API or automation tool, you have probably hit one of these errors:

  • “The media could not be fetched from this URI” (Instagram)
  • “Only photo or video can be accepted as media type” (Instagram)
  • “403 Restricted by robots.txt” (Facebook)

They are frustrating because they seem random. Your media URL works in a browser. Your robots.txt looks fine. But the API keeps rejecting your request.

Postproxy handles all three of these errors for you. If you are using the Postproxy API or MCP server, Postproxy takes care of media fetching, validation, and platform-specific upload requirements so these errors never reach your application.

But if you are building your own integration or debugging a broken workflow, here is what each error means and how to fix it.

Instagram: “The media could not be fetched from this URI”

This error comes from Instagram’s Graph API during the container creation step (POST /{ig-user-id}/media). When you publish to Instagram via the API, you pass an image_url or video_url parameter. Instagram’s servers then attempt to download that media from your URL using Meta’s crawler.

The full error response looks like this:

{
"error": {
"message": "Only photo or video can be accepted as media type.",
"type": "OAuthException",
"code": 9004,
"error_subcode": 2207052,
"is_transient": false,
"error_user_title": "Media download has failed...",
"error_user_msg": "The media could not be fetched from this URI..."
}
}

The error fires when Meta’s crawler cannot download the file at the URL you provided. The actual fetch is done server-side by Meta, not by your application. So even if the URL works perfectly in your browser, it can fail when Meta’s servers try to reach it.

Common causes

1. The URL is not publicly accessible

Instagram’s servers need to reach your URL from the public internet. If the media is behind authentication, on localhost, on a staging server, or requires a VPN, the fetch will fail.

2. Your server blocks Meta’s crawler

Meta fetches the media using the facebookexternalhit/1.1 user agent. If your CDN, WAF, or security plugin blocks bot traffic, Meta cannot download the file. Cloudflare’s “Bot Fight Mode” is a frequent offender.

Test what Meta’s crawler sees:

Terminal window
curl -A "facebookexternalhit/1.1" -I https://yourdomain.com/image.jpg

You need a 200 OK response with a valid Content-Type header.

3. robots.txt blocks the crawler

Meta’s crawler respects robots.txt. If your file includes a blanket disallow rule:

User-agent: *
Disallow: /

Meta’s servers will not fetch the media. Add an explicit allow for the crawler:

User-agent: facebookexternalhit
Allow: /

4. The URL redirects

If your media URL returns a 301 or 302 redirect, Meta’s crawler may not follow it correctly. Use the final, direct URL instead.

5. The URL is temporary or expired

Presigned S3 URLs, Google Drive share links, and other temporary URLs can expire before Meta’s servers fetch the media. If there is any delay between generating the URL and calling the API, the link may already be dead.

6. Certain image hosting services

Some hosting services (imgbb in particular) are unreliable with Meta’s crawler. Cloudinary, direct WordPress media URLs, and standard CDN-hosted files tend to work consistently.

Instagram: “Only photo or video can be accepted as media type”

This is the same error as above — error code 9004, subcode 2207052. The message field says “Only photo or video can be accepted as media type” while the error_user_msg field says “The media could not be fetched from this URI.” They are the same underlying failure.

However, this wording also fires when the media file itself is in an unsupported format.

Media format requirements

Instagram’s API only accepts JPEG images. Not PNG, not WebP, not HEIC. If your server serves the file with a Content-Type of text/html (common with misconfigured CDNs or redirects to error pages), Instagram sees HTML instead of an image and rejects it.

Other constraints:

  • Images must be under 8 MB
  • Videos must be in supported formats (MP4 with H.264)
  • CMYK color space images are not supported — use sRGB

The timing issue

If you generate a media URL and immediately call the Instagram API, the file may not be available yet. This happens with CDNs that have propagation delays or storage services that take a moment to make new uploads publicly accessible. Adding a short delay (a few seconds) before calling the API can resolve intermittent failures.

Facebook: “403 Restricted by robots.txt”

This error appears when sharing URLs on Facebook. When you post a link, Facebook’s crawler (facebookexternalhit/1.1) fetches the page to read Open Graph meta tags (og:title, og:description, og:image) and generate a link preview. If the crawler gets a 403 response, you see this in the Sharing Debugger:

Response Code: 403 “This response code could be due to a robots.txt block. Please allowlist facebookexternalhit on your site’s robots.txt config to utilize Facebook scraping.”

It is not always robots.txt

Facebook uses “robots.txt” as a catch-all explanation for any 403 response. The actual cause is often something else entirely.

WAF or CDN rules blocking bot traffic. Cloudflare, Akamai, and other CDNs may challenge or block Meta’s crawler even when robots.txt explicitly allows it. You need to create a WAF bypass rule for the facebookexternalhit user agent or whitelist Meta’s IP ranges (AS32934).

Security plugins. WordPress security plugins like Wordfence and iThemes Security often block the crawler at the application level. Check your plugin settings for bot-blocking rules.

Hosting platform defaults. Some hosting platforms (Azure Blob Storage, InfinityFree, and others) block bot traffic by default. Check your hosting provider’s documentation for crawler whitelisting.

Dynamic robots.txt generation. WordPress SEO plugins like AIOSEO can generate robots.txt dynamically, and caching or plugin conflicts can cause intermittent 403 responses — working one second, blocked the next.

How to fix it

Step 1: Verify the block

Terminal window
curl -A "facebookexternalhit/1.1" -I https://yoursite.com/page

If this returns 403, your server is blocking Meta’s crawler.

Step 2: Update robots.txt

User-agent: facebookexternalhit
Allow: /
User-agent: *
Disallow: /private/

Step 3: Whitelist in your WAF/CDN

Create a rule that allows requests with a user agent containing facebookexternalhit. In Cloudflare, this is a WAF custom rule with action “Skip.”

Step 4: Clear Facebook’s cache

Facebook caches robots.txt for up to 24 hours. After fixing the issue:

  1. Go to Facebook’s Sharing Debugger (developers.facebook.com/tools/debug/)
  2. Enter the affected URL
  3. Click “Scrape Again” to force a re-fetch

Or use the Graph API:

Terminal window
curl -X POST "https://graph.facebook.com/v25.0/?id=https://yoursite.com/page&scrape=true&access_token=YOUR_TOKEN"

Why these errors exist

All three errors share a root cause: Meta’s publishing infrastructure requires server-to-server media fetching. When you publish to Instagram via the API, you do not upload the image directly. You give Instagram a URL, and Instagram’s servers download it. When you share a link on Facebook, Facebook’s crawler fetches the page to build a preview.

This design means your media and pages must be accessible to Meta’s crawlers. Any layer in the chain — your server, your CDN, your WAF, your robots.txt, your hosting provider — can break the fetch.

How Postproxy avoids these errors

When you publish through the Postproxy API, Postproxy handles the entire media pipeline for you — fetching, validating, and delivering your media to each platform in the format it expects. You do not need to worry about crawler access, URL accessibility, or platform-specific upload quirks.

This means:

  • Your robots.txt configuration does not matter
  • Your CDN’s bot protection does not interfere
  • Temporary or presigned URLs work as long as they are valid when Postproxy fetches them
  • Media format validation happens before the platform API call, so you get a clear error message instead of a cryptic OAuthException

A single API call handles publishing to all connected platforms:

Terminal window
curl -X POST "https://api.postproxy.dev/api/posts" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"post": {
"body": "New post with media"
},
"profiles": ["instagram", "facebook", "twitter"],
"media": ["https://example.com/image.jpg"]
}'

Per-platform results tell you exactly what succeeded and what failed, instead of a single opaque error. If you are tired of debugging crawler access issues and media format rejections, try Postproxy and skip these errors entirely.

Ready to get started?

Start with our free plan and scale as your needs grow. No credit card required.