Kakao Share Thumbnail Not Showing? Here's the Fix (JavaScript SDK 2025)
Learn why Kakao Share thumbnails don't appear even with a valid imageUrl, and fix it using scrapImage to convert your URL into a KAGE CDN URL. Step-by-step guide.
Kakao Share Thumbnail Not Showing? Here's the Fix (JavaScript SDK 2025)
You've implemented KakaoTalk sharing and set imageUrl correctly — but the thumbnail simply doesn't appear in the share preview. If this sounds familiar, the root cause lies in Kakao's internal CDN policy. This guide covers the exact reason and the code fix, step by step.
![]()
Why Kakao Share Thumbnails Don't Show Up
When you pass an external image URL directly to the imageUrl field of sendDefault(), the thumbnail often fails to render.
// ❌ This won't show a thumbnail
Kakao.Share.sendDefault({
objectType: 'feed',
content: {
title: 'Share Title',
description: 'Share description',
imageUrl: 'https://example.com/my-image.png', // ← won't appear!
link: { webUrl: 'https://example.com', mobileWebUrl: 'https://example.com' },
},
});
Even if the image is publicly accessible, why does it fail?
Kakao serves share preview images through its own CDN (the KAGE server at
k.kakaocdn.net). When you pass an external URL toimageUrl, Kakao's server attempts to fetch and re-host the image on KAGE — and this process frequently fails silently, leaving the thumbnail blank.
The fix is to upload the image to KAGE yourself first, then pass the resulting KAGE URL to imageUrl.
Fix: Use scrapImage to Get a KAGE URL
The solution to Kakao share thumbnail issues is to call Kakao.Share.scrapImage() first, upload the image to KAGE, then use the returned URL in imageUrl.
// ✅ Fix: scrapImage → KAGE URL → sendDefault
const imageUrl = 'https://example.com/my-image.png';
// Step 1: Upload to Kakao KAGE server
const result = await Kakao.Share.scrapImage({ imageUrl });
const kageUrl = result.infos.original.url;
// → "http://k.kakaocdn.net/dn/xxxxx/kakaolink40_original.png"
// Step 2: Share using the KAGE URL
Kakao.Share.sendDefault({
objectType: 'feed',
content: {
title: 'Share Title',
description: 'Share description',
imageUrl: kageUrl, // ← use KAGE URL here
link: { webUrl: 'https://example.com', mobileWebUrl: 'https://example.com' },
},
});
Just two steps, and the KakaoTalk share thumbnail displays correctly.
Full Implementation with Caching
Calling scrapImage on every share triggers unnecessary API requests. Add a cache variable to upload only once and reuse the result.
let cachedKageUrl = null;
async function getKageImageUrl(imageUrl) {
if (cachedKageUrl) return cachedKageUrl;
try {
const result = await Kakao.Share.scrapImage({ imageUrl });
cachedKageUrl = result.infos.original.url;
return cachedKageUrl;
} catch (e) {
console.warn('scrapImage failed:', e);
return imageUrl; // fall back to original URL on failure
}
}
async function shareToKakao() {
const imageUrl = 'https://example.com/my-image.png';
const thumbUrl = await getKageImageUrl(imageUrl);
Kakao.Share.sendDefault({
objectType: 'feed',
content: {
title: 'Share Title',
description: 'Share description',
imageUrl: thumbUrl,
link: {
webUrl: 'https://example.com',
mobileWebUrl: 'https://example.com',
},
},
buttons: [
{
title: 'Learn More',
link: {
webUrl: 'https://example.com',
mobileWebUrl: 'https://example.com',
},
},
],
});
}
scrapImage vs uploadImage: What's the Difference?
The Kakao SDK provides two functions for uploading images to KAGE — it's easy to mix them up.
| API | Input | Use Case |
|---|---|---|
Kakao.Share.scrapImage({ imageUrl }) | URL string | Upload a server-hosted image to KAGE by URL |
Kakao.Share.uploadImage({ file }) | File object array | Upload a local file selected via <input type="file"> |
// ✅ Upload by URL
await Kakao.Share.scrapImage({ imageUrl: 'https://example.com/image.png' });
// ✅ Upload a file picked from a file input
const files = document.getElementById('file-input').files;
await Kakao.Share.uploadImage({ file: files });
// ❌ Passing a URL string to uploadImage will fail
await Kakao.Share.uploadImage({ file: ['https://example.com/image.png'] }); // won't work
Rule of thumb: use scrapImage for URLs, uploadImage for local files.
Kakao Share Opens the App Download Page on Desktop
Kakao.Share.sendDefault() relies on the KakaoTalk app being installed.
- Mobile (KakaoTalk installed) → Opens KakaoTalk and shares directly
- Desktop (KakaoTalk not installed) → Redirects to the KakaoTalk download page ← bad UX
Handle this gracefully by detecting the device type:
function isMobileDevice() {
return /Android|iPhone|iPad|iPod|webOS|BlackBerry|IEMobile|Opera Mini/i.test(
navigator.userAgent
);
}
async function handleKakaoShare(shareUrl) {
if (!isMobileDevice()) {
// Desktop: copy URL to clipboard and notify the user
await navigator.clipboard.writeText(shareUrl);
alert('Link copied! Paste it into KakaoTalk.');
return;
}
// Mobile: share via Kakao SDK
const thumbUrl = await getKageImageUrl('https://example.com/my-image.png');
Kakao.Share.sendDefault({
objectType: 'feed',
content: {
title: 'Share Title',
description: 'Share description',
imageUrl: thumbUrl,
link: { webUrl: shareUrl, mobileWebUrl: shareUrl },
},
});
}
Thumbnail Troubleshooting Checklist
If the thumbnail still isn't showing, go through this checklist in order:
| # | Check | Details |
|---|---|---|
| 1 | Using scrapImage? | External URLs can't be used directly. Always convert with scrapImage → KAGE URL |
| 2 | Image URL uses HTTPS? | HTTP is not supported |
| 3 | Image publicly accessible? | Run curl -I <imageUrl> and confirm you get a 200 OK |
| 4 | Standard port (80/443)? | Kakao's scraper cannot reach non-standard ports like 8000 or 3000 |
| 5 | File size under 5 MB? | Larger files will fail to upload |
| 6 | Domain registered in Kakao Console? | Go to App Settings → Platform → Web and add your site's domain |
| 7 | Testing on localhost? | Kakao's server can't reach localhost. Use a production image URL or a tunnel like ngrok |
[Photo suggestion: Screenshot of the Kakao Developers Console (developers.kakao.com) showing the Web platform domain registration section under App Settings]
Quick Diagnostic Script (Browser Console)
Paste this script in your browser's DevTools console to pinpoint the failure at each stage — image fetch, SDK init, and scrapImage.
(async () => {
const IMAGE_URL = 'https://example.com/my-image.png'; // ← your image URL
const KAKAO_KEY = 'your-kakao-js-key'; // ← your app key
// Step 1: Image accessibility check
console.log('1. Image accessibility check');
try {
const res = await fetch(IMAGE_URL, { method: 'HEAD' });
console.log(' Status:', res.status, '| Content-Type:', res.headers.get('content-type'));
} catch (e) {
console.error(' Image fetch failed:', e.message);
}
// Step 2: SDK initialization
if (!window.Kakao?.isInitialized()) {
if (!window.Kakao) {
await new Promise(r => {
const s = document.createElement('script');
s.src = 'https://t1.kakaocdn.net/kakao_js_sdk/2.7.4/kakao.min.js';
s.onload = r;
document.head.appendChild(s);
});
}
window.Kakao.init(KAKAO_KEY);
}
console.log('2. SDK initialized:', Kakao.isInitialized());
// Step 3: scrapImage test
console.log('3. scrapImage test');
try {
const result = await Kakao.Share.scrapImage({ imageUrl: IMAGE_URL });
console.log(' KAGE URL:', result.infos.original.url);
} catch (e) {
console.error(' scrapImage failed:', e);
}
})();
If scrapImage fails, check the error message — it usually points directly to the root cause (domain not registered, image inaccessible, file too large, etc.).
Notes on KAGE Image Expiry
- KAGE-hosted images are automatically deleted after up to 100 days
- Calling
scrapImageagain with the same URL issues a new KAGE URL - Cache the KAGE URL in a variable (like
cachedKageUrl) to avoid re-uploading on every share
Frequently Asked Questions
Q: I'm using scrapImage but the thumbnail still doesn't show. What should I check?
A: Work through checklist items 2–7 above. Verify that the image is served over HTTPS, uses a standard port (80 or 443), and that your domain is registered in the Kakao Developer Console. Run the diagnostic script in the browser console to identify exactly which step fails.
Q: Can I test Kakao Share thumbnails on localhost?
A: No. Kakao's servers cannot reach localhost, so scrapImage will fail. During development, point imageUrl to an image on a real server (production or staging), or use a tunneling tool like ngrok to expose your local server to the internet.
Q: How do I prevent the Kakao share button from opening the app download page on desktop?
A: Use isMobileDevice() or a similar check to branch between mobile and desktop. On desktop, fall back to copying the URL to the clipboard, as shown in the code example above.
Q: When should I use uploadImage vs scrapImage?
A: Use scrapImage({ imageUrl }) when your image is already hosted on a public server and you have its URL. Use uploadImage({ file }) when the user has selected a local file via a file input element and you want to upload it to KAGE directly.
Conclusion
The most common cause of a missing Kakao Share thumbnail is passing an external image URL directly to imageUrl. The fix is straightforward: call Kakao.Share.scrapImage() first to upload the image to Kakao's KAGE CDN, then pass the returned URL to sendDefault(). Combine this with the checklist and the diagnostic script, and you'll resolve thumbnail issues in minutes.
For the full API reference, see the Kakao JavaScript SDK — KakaoTalk Share documentation.
Found this useful? Share it
Latest posts
How to Generate CRM User Manuals in 20 Minutes with Claude Code Sub-Agents
Learn how Claude Code sub-agents can analyze your CRM codebase and auto-generate user manuals and visual guidebooks in just 20 minutes. See the real-world results.
GEO Generative Engine Optimization: The Complete 2025 AI Marketing Strategy Guide
Learn what GEO (Generative Engine Optimization) is, how it differs from traditional SEO, and discover 5 proven AI marketing strategies to get cited by AI search engines in 2025.
Related projects
Get new posts by email
Insights on marketing, analytics, and dev, delivered to your inbox.