Instagram接口返回图片URL报NotSameOrigin跨域加载失败
问题描述
- 开发API用于获取Instagram指定话题标签下的相关数据,调用接口返回的JSON数据包含不同分辨率的图片URL,但直接使用这些URL加载图片时触发错误,图片无法正常展示。
- 调用的接口地址:
https://www.instagram.com/explore/tags/jeep/?__a=1 - 触发的错误信息:
GET 对应Instagram CDN图片地址 net::ERR_BLOCKED_BY_RESPONSE.NotSameOrigin 200 - 后端基于Express搭建,已配置cors中间件;前端通过fetch调用本地
/hashtag接口拿到Instagram返回的数据后,提取每条内容的thumbnail_src字段赋值给动态创建的img标签src属性,触发上述跨域拦截错误。
现有后端代码(Index.js)
const express = require("express"); const morgan = require("morgan"); const bodyParser = require("body-parser"); // Routes const routeLogin = require('./routes/login'); const routeRegister = require('./routes/register'); const routeHashtags = require('./routes/hashtag'); const app = express(); const cors = require("cors"); // Use app.use(cors()) // Morgan app.use(morgan("dev")); // Body parser app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); // Routes app.use('/login', routeLogin); app.use('/register', routeRegister); app.use('/hashtag', routeHashtags); // Error app.use((req, res, next) => { const error = new Error("Erro! Não encontrado!"); error.status = 404; next(error); }) app.use((error, req, res, next) => { res.status(error.status || 500); return res.send({ error: { message: error.message } }) }) module.exports = app;
现有前端渲染代码
async function dashboard(){ async function pendingPosts(){ let divPendImages = document.getElementById("pendingPosts_images"); let ctaNo = document.getElementById("pendingPosts_cta_no") let ctaYes = document.getElementById("pendingPosts_cta_yes") // Get data const res = await fetch("http://localhost:3120/hashtag/") .then((res) => res.json()) .then((data) => {return data.response}) // Show data function showData(){ console.log(res.length) res.forEach((element, index) => { // Img let img = document.createElement("img") let src = element.node.thumbnail_src; img.src = src; ctaNo.parentNode.querySelector("input").value = src; ctaYes.parentNode.querySelector("input").value = src; // CTA if(index == 0){ ctaNo.parentNode.action = `http://localhost:3120/hashtag/notadd/${element.node.id}`; ctaYes.parentNode.action = `http://localhost:3120/hashtag/create/${element.node.id}`; } // Append img divPendImages.appendChild(img); }); } showData() } pendingPosts() } dashboard()
问题原因
这个报错和你本地服务配置的CORS规则无关。Instagram CDN返回图片资源时携带了Cross-Origin-Resource-Policy: same-origin响应头,浏览器会强制拦截非Instagram域名下的页面对该资源的直接引用,所以哪怕接口能正常拿到图片URL,前端直接写入img标签src也会被拦截加载失败。
解决方案
核心思路是避免前端直接请求Instagram CDN资源,由你自己的后端服务代理请求图片,再返回给前端,从根源绕过跨域限制。
- 后端安装请求依赖,用于拉取Instagram图片资源:
npm install axios
- 在Express服务中新增图片代理路由,添加位置和现有路由配置平级即可:
const axios = require('axios'); // 图片代理路由 app.get('/proxy/ig-image', async (req, res) => { try { const imgUrl = req.query.url; if (!imgUrl) { return res.status(400).send('缺少图片地址参数'); } // 后端发起请求拉取Instagram图片 const response = await axios.get(imgUrl, { responseType: 'arraybuffer', headers: { // 模拟常规浏览器请求头,避免被Instagram反爬拦截 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36', 'Referer': 'https://www.instagram.com/' } }); // 设置正确的响应头,允许前端跨域访问 res.set('Content-Type', response.headers['content-type']); res.set('Cross-Origin-Resource-Policy', 'cross-origin'); res.send(response.data); } catch (err) { res.status(500).send('图片加载失败'); } });
- 修改前端图片地址赋值逻辑,将原Instagram CDN地址替换为本地代理接口地址:
// 原逻辑:直接使用Instagram返回的图片地址 // let src = element.node.thumbnail_src; // 替换为代理接口地址 let src = `http://localhost:3120/proxy/ig-image?url=${encodeURIComponent(element.node.thumbnail_src)}`; img.src = src;
如果前后端同端口部署,可以直接写相对路径/proxy/ig-image?url=xxx。
临时测试可以尝试给img标签添加
referrerpolicy="no-referrer"属性,部分场景下可以绕过拦截,但稳定性极差,Instagram调整规则后就会失效,不建议生产环境使用。
内容的提问来源于stack exchange,提问作者GabssRuizz
相关产品推荐
相关产品推荐

