Forum Discussion
Unable to load images in Link Unfurling Card
- Jun 04, 2025
Hello Tmbull,
You're encountering this issue because Microsoft Teams' link unfurling uses a proxy service (urlp/v1/url/content) to retrieve and cache external images. This service enforces strict content-type and security requirements. The 415 "Unsupported Media Type" error likely stems from one of the following:
🔍 Root Causes
- Content-Type Not Properly Set
Teams expects image responses to include a valid Content-Type like image/png or image/jpeg. Ngrok sometimes serves images via local servers that misconfigure or omit this header. - Missing Content-Length or CORS Headers
If the image response lacks proper Content-Length or security headers (like Access-Control-Allow-Origin), Teams' proxy might reject it. - Image Stream or Encoding Issues
Serving images via dev servers (like Flask, Express, or even raw file streaming) may cause subtle issues, such as incorrect byte streams, that Teams interprets as corrupted. - Ngrok Public URL Limitations
While not explicitly banned, ngrok-free URLs can be rate-limited, ephemeral, or flagged for unusual activity. Microsoft documentation recommends them for debugging, but not guaranteed for content ingestion via production pipelines like urlp.
✅ Recommended Fixes
- Host Images on a Static CDN or Blob Storage
Use Azure Blob Storage with public access or GitHub raw URLs (as you've already tested successfully) to ensure stable, compliant hosting. - Verify Headers
Ensure your image server returns:
Content-Type: image/png
Content-Length: [exact byte size]
Cache-Control: public, max-age=86400
Avoid redirects and ensure direct delivery of the image - Use HTTPS with Valid Certificate
Ngrok must serve over HTTPS with a valid TLS certificate. Teams will reject self-signed or invalid certs. - Use Known-Compatible Hosts in Dev
For development, tools like https://imgur.com/ or https://imagekit.io/ allow free image hosting and are trusted by Microsoft endpoints.
- Content-Type Not Properly Set
Hello Tmbull,
You're encountering this issue because Microsoft Teams' link unfurling uses a proxy service (urlp/v1/url/content) to retrieve and cache external images. This service enforces strict content-type and security requirements. The 415 "Unsupported Media Type" error likely stems from one of the following:
🔍 Root Causes
- Content-Type Not Properly Set
Teams expects image responses to include a valid Content-Type like image/png or image/jpeg. Ngrok sometimes serves images via local servers that misconfigure or omit this header. - Missing Content-Length or CORS Headers
If the image response lacks proper Content-Length or security headers (like Access-Control-Allow-Origin), Teams' proxy might reject it. - Image Stream or Encoding Issues
Serving images via dev servers (like Flask, Express, or even raw file streaming) may cause subtle issues, such as incorrect byte streams, that Teams interprets as corrupted. - Ngrok Public URL Limitations
While not explicitly banned, ngrok-free URLs can be rate-limited, ephemeral, or flagged for unusual activity. Microsoft documentation recommends them for debugging, but not guaranteed for content ingestion via production pipelines like urlp.
✅ Recommended Fixes
- Host Images on a Static CDN or Blob Storage
Use Azure Blob Storage with public access or GitHub raw URLs (as you've already tested successfully) to ensure stable, compliant hosting. - Verify Headers
Ensure your image server returns:
Content-Type: image/png
Content-Length: [exact byte size]
Cache-Control: public, max-age=86400
Avoid redirects and ensure direct delivery of the image - Use HTTPS with Valid Certificate
Ngrok must serve over HTTPS with a valid TLS certificate. Teams will reject self-signed or invalid certs. - Use Known-Compatible Hosts in Dev
For development, tools like https://imgur.com/ or https://imagekit.io/ allow free image hosting and are trusted by Microsoft endpoints.
Thank you for the reply. I verified all of the headers matched between my ngrok host and the GitHub raw URL and I also hashed the content of the downloaded files and they both matched. So I could not find any differences. So it seems there is something about the ngrok host or responses that the proxy service does not like, but I could not detect it.
However, I took your advice and setup a static CDN (which is what we will do in higher environments anyway) and that worked as expected. So I think we can consider this resolved.