insta video downlord
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="theme-color" content="#dc2743">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="manifest" href="data:application/json;charset=utf-8,%7B%22name%22%3A%22InstaSaver%22%2C%22short_name%22%3A%22InstaSaver%22%2C%22start_url%22%3A%22.%22%2C%22display%22%3A%22standalone%22%2C%22background_color%22%3A%22%23f5f7fa%22%2C%22theme_color%22%3A%22%23dc2743%22%7D">
<title>InstaSaver - Quick Instagram Video Downloader</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* Custom styles for animations and specific tweaks */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
}
.glass-panel {
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
}
.gradient-text {
background: linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.btn-gradient {
background: linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.btn-gradient:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(220, 39, 67, 0.3);
}
.btn-gradient:active {
transform: translateY(0);
}
/* Loading spinner animation */
.spinner {
border: 4px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top: 4px solid #fff;
width: 24px;
height: 24px;
-webkit-animation: spin 1s linear infinite;
animation: spin 1s linear infinite;
display: inline-block;
vertical-align: middle;
}
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.hidden { display: none !important; }
</style>
</head>
<body class="flex flex-col items-center justify-center p-4">
<main class="w-full max-w-md glass-panel rounded-3xl p-8 mt-10 transition-all duration-300">
<header class="text-center mb-8">
<div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-white shadow-lg mb-4">
<i class="fab fa-instagram text-3xl" style="color: #dc2743;"></i>
</div>
<h1 class="text-3xl font-bold mb-2 text-gray-800">InstaSaver</h1>
<p class="text-gray-500 text-sm">Download Instagram Reels & Videos</p>
</header>
<section id="inputSection" class="space-y-6">
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-link text-gray-400"></i>
</div>
<input type="url" id="igLink"
class="w-full pl-10 pr-12 py-4 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-transparent bg-white/50 transition-all"
placeholder="Paste Instagram link here..."
autocomplete="off">
<button id="pasteBtn" class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm font-medium text-pink-600 hover:text-pink-800 focus:outline-none">
Paste
</button>
</div>
<button id="fetchBtn" class="w-full btn-gradient text-white font-semibold py-4 rounded-xl shadow-md flex items-center justify-center gap-2">
<span id="btnText">Get Download Link</span>
<div id="btnSpinner" class="spinner hidden"></div>
</button>
</section>
<section id="resultSection" class="hidden mt-8 pt-6 border-t border-gray-200/50">
<div class="text-center mb-4">
<h3 class="font-semibold text-gray-700">Video Ready!</h3>
<p class="text-xs text-gray-500">Preview below</p>
</div>
<div class="relative rounded-xl overflow-hidden bg-gray-100 aspect-[9/16] mb-4 shadow-inner flex items-center justify-center" id="previewContainer">
<!-- Placeholder for video preview -->
<i class="fas fa-video text-gray-400 text-4xl"></i>
</div>
<div class="space-y-3">
<a id="downloadLinkBtn" href="#" target="_blank" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 rounded-xl flex items-center justify-center gap-2 transition-colors shadow-md">
<i class="fas fa-download"></i> Download Video
</a>
<button id="resetBtn" class="w-full bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-3 rounded-xl flex items-center justify-center gap-2 transition-colors">
<i class="fas fa-redo"></i> Download Another
</button>
</div>
</section>
<div id="messageBox" class="hidden mt-4 p-3 rounded-lg text-sm text-center font-medium transition-all">
<!-- Messages will appear here -->
</div>
</main>
<footer class="mt-8 text-center text-gray-500 text-xs">
<p>This tool is for educational purposes.</p>
<p>Please respect creators' copyrights.</p>
</footer>
<script>
document.addEventListener('DOMContentLoaded', () => {
const igLinkInput = document.getElementById('igLink');
const pasteBtn = document.getElementById('pasteBtn');
const fetchBtn = document.getElementById('fetchBtn');
const btnText = document.getElementById('btnText');
const btnSpinner = document.getElementById('btnSpinner');
const resultSection = document.getElementById('resultSection');
const downloadLinkBtn = document.getElementById('downloadLinkBtn');
const resetBtn = document.getElementById('resetBtn');
const previewContainer = document.getElementById('previewContainer');
const messageBox = document.getElementById('messageBox');
// --- UI Helper Functions ---
function showMessage(msg, type = 'error') {
messageBox.textContent = msg;
messageBox.classList.remove('hidden', 'bg-red-100', 'text-red-700', 'bg-green-100', 'text-green-700', 'bg-blue-100', 'text-blue-700');
if (type === 'error') {
messageBox.classList.add('bg-red-100', 'text-red-700');
} else if (type === 'success') {
messageBox.classList.add('bg-green-100', 'text-green-700');
} else {
messageBox.classList.add('bg-blue-100', 'text-blue-700');
}
// Auto hide after 4 seconds
setTimeout(() => {
messageBox.classList.add('hidden');
}, 4000);
}
function setLoading(isLoading) {
if (isLoading) {
btnText.textContent = 'Processing...';
btnSpinner.classList.remove('hidden');
fetchBtn.disabled = true;
fetchBtn.classList.add('opacity-75', 'cursor-not-allowed');
} else {
btnText.textContent = 'Get Download Link';
btnSpinner.classList.add('hidden');
fetchBtn.disabled = false;
fetchBtn.classList.remove('opacity-75', 'cursor-not-allowed');
}
}
function validateInstagramLink(url) {
try {
const parsedUrl = new URL(url);
// Basic check to see if it's an instagram domain
return parsedUrl.hostname.includes('instagram.com') && (url.includes('/p/') || url.includes('/reel/') || url.includes('/tv/'));
} catch (e) {
return false;
}
}
// --- Event Listeners ---
// Handle Paste Button
pasteBtn.addEventListener('click', async () => {
try {
const text = await navigator.clipboard.readText();
igLinkInput.value = text;
showMessage('Link pasted from clipboard', 'info');
} catch (err) {
// Fallback if clipboard API is blocked (common in iframes without permissions)
showMessage('Please paste manually (Ctrl+V or long press)', 'error');
}
});
// Handle Reset
resetBtn.addEventListener('click', () => {
resultSection.classList.add('hidden');
igLinkInput.value = '';
previewContainer.innerHTML = '<i class="fas fa-video text-gray-400 text-4xl"></i>';
igLinkInput.focus();
});
// Handle Fetch Action
fetchBtn.addEventListener('click', async () => {
const url = igLinkInput.value.trim();
if (!url) {
showMessage('Please enter a valid Instagram link.', 'error');
return;
}
if (!validateInstagramLink(url)) {
showMessage('Invalid link. Please provide a link to a Reel or Post.', 'error');
return;
}
setLoading(true);
resultSection.classList.add('hidden');
// IMPORTANT NOTE FOR USER:
// Downloading directly from Instagram requires a backend API because
// Instagram blocks direct frontend requests (CORS issues) and heavily obfuscates their video URLs.
// Since this must be a self-contained frontend app without a custom backend provided,
// we simulate the API call to demonstrate functionality.
// In a real production app, you would send 'url' to your own server,
// which would scrape/use an official API to return the direct .mp4 link.
try {
// Simulating network delay for realism
await new Promise(resolve => setTimeout(resolve, 2000));
// --- MOCK RESPONSE DATA ---
// In real life, replace this with: const response = await fetch(`YOUR_BACKEND_URL?url=${encodeURIComponent(url)}`); const data = await response.json();
const mockDirectVideoUrl = "https://www.w3schools.com/html/mov_bbb.mp4"; // Placeholder dummy video
const mockThumbnail = "https://placehold.co/400x700/eeeeee/888888?text=Video+Preview";
// Update UI with "results"
previewContainer.innerHTML = `
<video class="w-full h-full object-cover" controls poster="${mockThumbnail}">
<source src="${mockDirectVideoUrl}" type="video/mp4">
Your browser does not support the video tag.
</video>
`;
// Set download link
downloadLinkBtn.href = mockDirectVideoUrl;
// Note: 'download' attribute only works for same-origin URLs in most modern browsers.
// For cross-origin (like an actual IG video), users usually have to right-click -> save,
// or the backend must proxy the download with specific headers.
downloadLinkBtn.setAttribute('download', 'instasaver_video.mp4');
showMessage('Video found successfully!', 'success');
resultSection.classList.remove('hidden');
} catch (error) {
console.error("Error fetching video:", error);
showMessage('Failed to fetch video. Please check the link or try again later.', 'error');
} finally {
setLoading(false);
}
});
// Allow hitting Enter in input field
igLinkInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
fetchBtn.click();
}
});
});
</script>
</body>
</html>
Comments
Post a Comment