Instagram'dan Açık Veri Kazıma Rehberi: Proxy Kullanımı ve En İyi Uygulamalar

Bu rehber, Instagram'ın halka açık verilerini residential proxy'ler kullanarak etik ve güvenli bir şekilde nasıl çekebileceğinizi açıklar. Rate limit, anti-bot ve fingerprinting zorluklarını aşın.

Instagram'dan Açık Veri Kazıma Rehberi: Proxy Kullanımı ve En İyi Uygulamalar

Instagram veri kazıma, sosyal medya dinleme araçları, pazar araştırması ve trend analizi yapan geliştiriciler için değerli bir yetenktir. Ancak platform, ölçekli veri çekmeyi zorlaştıran çok katmanlı korumalar uygulamıştır. Bu rehber, yalnızca halka açık verilere odaklanarak, residential proxy'lerin neden vazgeçilmez olduğunu ve Python ile güvenli, etik bir veri hattı kurmayı anlatır.

Önemli Uyarı: Bu rehber yalnızca herkesin erişebildiği açık verileri çekmeyi kapsar. Instagram'ın Hizmet Koşulları'nı (ToS), ABD'de CFAA'yı ve AB'de GDPR'yi ihlal edecek otomatik giriş (login automation), özel profil verisi çekme veya spam faaliyetleri teşvik etmez. Her zaman robots.txt'ye saygı gösterin ve kendi hız sınırlarınızı uygulayın.

Instagram Neden Kazıma İçin Zor Bir Hedef?

Instagram, 2018'den beri agresif anti-bot önlemleri uyguluyor. Ölçekli veri çekerken karşılaşacağınız başlıca engeller şunlardır:

Rate Limit ve 429 Hataları

Instagram, IP başına saatlik istek sayısını sıkı şekilde sınırlar. Anonim oturumlar için bu limit çok düşüktür — genellikle 100-200 istek/saat civarında. Bu sınırı aştığınızda HTTP 429 Too Many Requests alırsınız ve IP geçici olarak banlanır.

Login Wall (Giriş Duvarı)

Profil sayfalarının çoğu, yorumlar ve bazı medya içerikleri artık giriş yapmadan görüntülenemiyor. Ancak public profiller, hashtag sayfaları, location sayfaları ve Reels feed'leri hala giriş olmadan erişilebilir durumda.

Device Fingerprinting

Instagram, sadece IP'yi değil, tarayıcı parmak izinizi de analiz eder: User-Agent, ekran çözünürlüğü, font listesi, canvas fingerprint, WebGL render bilgisi ve JavaScript davranışları. Şüpheli desenler algıladığında CAPTCHA veya challenge sayfasına yönlendirir.

HTTPS Pinning ve API Erişimi

Instagram mobil uygulaması, sunucu sertifikasını doğrulayan certificate pinning kullanır. Bu, man-in-the-middle proxy'lerle trafiği yakalamayı zorlaştırır. Web arayüzü ise GraphQL endpoint'lerini kullanır ve bu endpoint'ler belirli header'lar olmadan çalışmaz.

Giriş Olmadan Erişilebilir Veriler

Instagram'da giriş yapmadan erişebileceğiniz veriler sınırlı ama değerlidir:

Veri TürüErişimNotlar
Public Profil Sayfaları✅ AçıkKullanıcı adı, biyografi, takipçi sayısı, gönderi sayısı
Hashtag Sayfaları✅ AçıkSon gönderiler, toplam gönderi sayısı
Location (Konum) Sayfaları✅ AçıkMekâna ait gönderiler
Reels Feed✅ KısmenSınırlı sayıda görüntüleme
Yorumlar❌ Giriş GerekliArtık login wall arkasında
Story'ler❌ Giriş GerekliSadece giriş yapan kullanıcılar görebilir
Private Profiller❌ AslaEtik ve yasal olarak erişilmemeli

Neden Residential Proxy'ler Zorunludur?

Instagram, datacenter IP'leri agresif şekilde işaretler. AWS, Google Cloud, DigitalOcean gibi bilinen datacenter bloklarından gelen istekler anında şüpheyle karşılanır. Bunu nedeni basit: gerçek kullanıcılar datacenter'dan değil, ev internetinden veya mobil bağlantılardan gelir.

Datacenter vs Residential Karşılaştırması

ÖzellikDatacenter ProxyResidential Proxy
IP KaynağıSunucu bloklarıGerçek ISP'ler (ev/mobil)
Instagram AlgısıHemen tespit edilirGerçek kullanıcı gibi görünür
Ban RiskiÇok YüksekDüşük-Orta
MaliyetDüşükOrta-Yüksek
HızÇok HızlıDeğişken
Uzun Vadeli KullanımÖnerilmezÖnerilir

Residential proxy'ler, gerçek İSS'lerden (ISP) tahsis edilmiş IP'ler kullanır. Instagram bu IP'leri normal kullanıcı trafiği olarak görür. Web kazıma projelerinde residential proxy kullanımı, başarı oranını dramatik şekilde artırır.

Python ile Instagram Veri Çekme

Aşağıda, ProxyHat residential proxy havuzu kullanarak Instagram public profil verisi çeken bir Python örneği var. Bu kod gerçekçi header'lar, User-Agent rotasyonu ve oturum izolasyonu kullanır.

Temel Yapı: Proxy ile İstek

import requests
import random
import time
from fake_useragent import UserAgent

# ProxyHat residential proxy konfigürasyonu
PROXY_GATEWAY = "gate.proxyhat.com"
PROXY_PORT = 8080
PROXY_USER = "your_username"
PROXY_PASS = "your_password"

# Ülke bazlı geo-targeting örneği
# user-country-US, user-country-DE, user-country-TR gibi
PROXY_URL = f"http://{PROXY_USER}-country-US:{PROXY_PASS}@{PROXY_GATEWAY}:{PROXY_PORT}"

PROXIES = {
    "http": PROXY_URL,
    "https": PROXY_URL
}

# Gerçekçi User-Agent havuzu
USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
    "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0"
]

def get_realistic_headers():
    """Instagram'ın beklediği gerçekçi header'lar"""
    return {
        "User-Agent": random.choice(USER_AGENTS),
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
        "Accept-Encoding": "gzip, deflate, br",
        "DNT": "1",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "none",
        "Sec-Fetch-User": "?1",
    }

def fetch_profile_page(username: str, session: requests.Session) -> dict:
    """Instagram public profil sayfasını çeker"""
    url = f"https://www.instagram.com/{username}/"
    
    headers = get_realistic_headers()
    headers["Referer"] = "https://www.google.com/"
    
    try:
        response = session.get(
            url,
            headers=headers,
            proxies=PROXIES,
            timeout=30
        )
        
        if response.status_code == 200:
            return parse_profile_html(response.text, username)
        elif response.status_code == 429:
            print(f"Rate limit hit. Waiting before retry...")
            time.sleep(60)
            return None
        else:
            print(f"Unexpected status: {response.status_code}")
            return None
            
    except requests.RequestException as e:
        print(f"Request failed: {e}")
        return None

def parse_profile_html(html: str, username: str) -> dict:
    """HTML'den profil verisini ayrıştırır"""
    import re
    
    # Instagram profil verisi <script type="text/javascript"> içinde JSON olarak gömülü
    pattern = r'window\.__additionalDataLoaded\(\[\],\s*({.*?})\)\s*;\s*</script>'
    match = re.search(pattern, html, re.DOTALL)
    
    if match:
        import json
        try:
            data = json.loads(match.group(1))
            user_data = data.get("graphql", {}).get("user", {})
            
            return {
                "username": username,
                "full_name": user_data.get("full_name"),
                "biography": user_data.get("biography"),
                "followers": user_data.get("edge_followed_by", {}).get("count"),
                "following": user_data.get("edge_follow", {}).get("count"),
                "posts_count": user_data.get("edge_owner_to_timeline_media", {}).get("count"),
                "is_private": user_data.get("is_private"),
                "is_verified": user_data.get("is_verified"),
            }
        except json.JSONDecodeError:
            pass
    
    return {"username": username, "error": "Could not parse profile data"}

# Kullanım
if __name__ == "__main__":
    session = requests.Session()
    profile = fetch_profile_page("instagram", session)
    print(profile)

Oturum İzolasyonu ve IP Rotasyonu

Her istek için yeni bir IP kullanmak, ban riskini azaltır. ProxyHat'te her istekte farklı bir residential IP almak için username'de -session- parametresini kullanabilirsiniz:

import uuid

def get_rotating_proxy_url(country: str = "US") -> str:
    """Her istekte yeni IP için rastgele session ID kullan"""
    session_id = str(uuid.uuid4())[:8]
    return f"http://{PROXY_USER}-country-{country}-session-{session_id}:{PROXY_PASS}@{PROXY_GATEWAY}:{PROXY_PORT}"

def fetch_with_rotation(url: str) -> requests.Response:
    """Her istekte yeni IP ile fetch"""
    proxy_url = get_rotating_proxy_url()
    proxies = {"http": proxy_url, "https": proxy_url}
    
    session = requests.Session()
    return session.get(url, headers=get_realistic_headers(), proxies=proxies, timeout=30)

Instagram'a Özgü Teknik Zorluklar

?__a=1 JSON Endpoint

Eskiden https://www.instagram.com/username/?__a=1 URL'si doğrudan JSON döndürürdü. Instagram bu endpoint'i 2021'de kısıtladı. Artık çalışmıyor veya login gerektiriyor. Bunun yerine HTML kaynağından gömülü JSON'u ayrıştırmak gerekiyor.

GraphQL Sorguları

Instagram web arayüzü, dahili GraphQL API kullanır. Bu API'ye erişmek için:

# Instagram GraphQL query örneği (sürekli değişir, reverse engineering gerekir)
GRAPHQL_URL = "https://www.instagram.com/graphql/query/"

headers = {
    **get_realistic_headers(),
    "x-ig-app-id": "936619743392459",  # Instagram web app ID
    "x-csrftoken": get_csrf_token(),  # Cookie'den alınmalı
    "x-requested-with": "XMLHttpRequest",
}

# Query hash'leri zamanla değişir
query_hash = "1c91b5bb5e9b5d6c7c7e5d5d5d5d5d5d"
params = {
    "query_hash": query_hash,
    "variables": f'{{"username":"instagram"}}'
}

Uyarı: GraphQL query hash'leri ve x-ig-app-id değeri Instagram tarafından düzenli olarak değiştirilir. Reverse engineering sürekli bakım gerektirir.

x-ig-app-id ve x-csrftoken Header'ları

Instagram API istekleri için gerekli header'lar:

  • x-ig-app-id: Instagram web uygulamasının sabit ID'si (936619743392459)
  • x-csrftoken: İlk sayfa ziyaretinden alınan CSRF token
  • x-requested-with: XMLHttpRequest olmalı

HTML'den JSON Ayrıştırma

En güvenilir yöntem, profil sayfasının HTML'ini çekip içinde gömülü JavaScript verisini ayrıştırmaktır:

import re
import json

def extract_embedded_json(html: str) -> dict:
    """HTML içindeki __additionalDataLoaded veya __bbox verisini bul"""
    
    # Yöntem 1: additionalDataLoaded
    pattern1 = r'window\.__additionalDataLoaded\(\[\],\s*({.*?})\)\s*;'
    match = re.search(pattern1, html, re.DOTALL)
    
    if match:
        try:
            return json.loads(match.group(1))
        except:
            pass
    
    # Yöntem 2: _sharedData
    pattern2 = r'window\._sharedData\s*=\s*({.*?});\s*</script>'
    match = re.search(pattern2, html, re.DOTALL)
    
    if match:
        try:
            return json.loads(match.group(1))
        except:
            pass
    
    return {}

Hız Sınırlama ve Rate Limit Yönetimi

Instagram'ın rate limit'lerini aşmamak için kendi hız sınırlarınızı uygulayın:

import time
from collections import deque

class RateLimiter:
    def __init__(self, requests_per_hour: int = 100, min_interval: float = 3.0):
        self.requests_per_hour = requests_per_hour
        self.min_interval = min_interval
        self.request_times = deque()
    
    def wait_if_needed(self):
        """Gerekirse bekle"""
        now = time.time()
        
        # Minimum interval bekle
        if self.request_times:
            elapsed = now - self.request_times[-1]
            if elapsed < self.min_interval:
                time.sleep(self.min_interval - elapsed)
        
        # Saatlik limit kontrolü
        hour_ago = now - 3600
        while self.request_times and self.request_times[0] < hour_ago:
            self.request_times.popleft()
        
        if len(self.request_times) >= self.requests_per_hour:
            wait_time = 3600 - (now - self.request_times[0])
            print(f"Hourly limit reached. Waiting {wait_time:.0f} seconds...")
            time.sleep(wait_time)
        
        self.request_times.append(time.time())

# Kullanım
limiter = RateLimiter(requests_per_hour=80, min_interval=4.0)

for username in target_usernames:
    limiter.wait_if_needed()
    profile = fetch_profile_page(username, session)
    # process profile...

Node.js Örneği

JavaScript/TypeScript ortamında da benzer bir yaklaşım kullanılabilir:

const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

const PROXY_HOST = 'gate.proxyhat.com';
const PROXY_PORT = 8080;
const PROXY_USER = 'your_username';
const PROXY_PASS = 'your_password';

// ProxyHat ile residential proxy
const proxyUrl = `http://${PROXY_USER}-country-US:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}`;
const httpsAgent = new HttpsProxyAgent(proxyUrl);

const userAgents = [
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15',
];

async function fetchInstagramProfile(username) {
  const url = `https://www.instagram.com/${username}/`;
  
  const headers = {
    'User-Agent': userAgents[Math.floor(Math.random() * userAgents.length)],
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
  };
  
  try {
    const response = await axios.get(url, {
      headers,
      httpsAgent,
      timeout: 30000,
    });
    
    if (response.status === 200) {
      return parseProfileFromHtml(response.data, username);
    }
  } catch (error) {
    if (error.response?.status === 429) {
      console.log('Rate limited. Waiting...');
      await new Promise(r => setTimeout(r, 60000));
    }
    throw error;
  }
}

function parseProfileFromHtml(html, username) {
  const regex = /window\.__additionalDataLoaded\(\[\],\s*({.*?})\)\s*;/s;
  const match = html.match(regex);
  
  if (match) {
    const data = JSON.parse(match[1]);
    const user = data.graphql?.user;
    
    return {
      username,
      fullName: user?.full_name,
      followers: user?.edge_followed_by?.count,
      posts: user?.edge_owner_to_timeline_media?.count,
      isPrivate: user?.is_private,
    };
  }
  
  return { username, error: 'Parse failed' };
}

module.exports = { fetchInstagramProfile };

Etik Veri Kazıma İlkeleri

Instagram'dan veri çekerken etik sınırları aşmamak kritiktir:

Robots.txt'ye Saygı

Instagram'ın robots.txt'si birçok endpoint'i engeller. Buna saygı gösterin:

# instagram.com/robots.txt (özet)
User-agent: *
Disallow: /accounts/
Disallow: /p/
Disallow: /explore/
Allow: /$
Allow: /$username/$

Kendi Hız Sınırlarınızı Uygulayın

Instagram'ın izin verdiğinden daha yavaş istek atın. Saatte 50-80 istek güvenli bir aralıktır. ProxyHat pricing sayfasında farklı kullanım senaryoları için uygun planları bulabilirsiniz.

Asla Otomatik Giriş Yapmayın

Otomatik login denemeleri:

  • Instagram ToS'yi ihlal eder
  • Hesabınızın kalıcı olarak banlanmasına neden olur
  • ABD'de CFAA kapsamında yasal risk oluşturabilir
  • GDPR kapsamında veri gizliliği ihlali sayılabilir

Resmi API'yi Tercih Edin

Uzun vadeli projeler için Instagram Graph API'yi kullanmayı düşünün:

  • Onaylı iş ortakları için resmi erişim
  • Rate limit'ler belirli ve öngörülebilir
  • ToS uyumlu
  • Değişen API'ler için bakım gerektirmez

Resmi API erişimi alınamıyorsa, yalnızca halka açık verileri çekin ve bunu düşük hacimle yapın.

Sık Karşılaşılan Sorunlar ve Çözümleri

SorunOlası NedenÇözüm
429 Too Many RequestsIP başına limit aşıldıResidential proxy rotasyonu, istek hızını düşür
403 ForbiddenBot tespitiHeader'ları iyileştir, fingerprint'i değiştir
Boş JSONEndpoint değişmişHTML ayrıştırma yöntemini güncelle
CAPTCHAŞüpheli davranışProxy kalitesini artır, hızını düşür
TimeoutProxy yavaşTimeout süresini artır, farklı proxy dene

Key Takeaways

  • Residential proxy kullanın: Datacenter IP'ler Instagram'da anında tespit edilir. ProxyHat'ın global residential ağı gerçek ISP IP'leri sağlar.
  • Sadece halka açık verilere odaklanın: Private profiller, story'ler ve yorumlar etik ve yasal olarak erişilmemeli.
  • Hız sınırlayın: Saatte 50-80 istek, istekler arası 3-5 saniye güvenli bir aralıktır.
  • HTML ayrıştırma kullanın: ?__a=1 artık güvenilir değil, gömülü JSON'u ayrıştırın.
  • Otomatik login yapmayın: Bu ToS ihlali ve yasal risk oluşturur.
  • Bakım yapın: Instagram HTML yapısı ve GraphQL endpoint'leri düzenli değişir.
  • Resmi API'yi değerlendirin: Uzun vadeli projeler için Instagram Graph API en güvenli yoldur.

Instagram veri kazıma, doğru araçlar ve etik yaklaşımla mümkündür. Residential proxy'ler, gerçekçi header'lar ve akıllı hız sınırlama ile güvenilir bir veri hattı kurabilirsiniz. ProxyHat, SERP tracking ve sosyal medya dinleme projeleri için yüksek kaliteli residential proxy'ler sunar.

Başlamaya hazır mısınız?

148+ ülkede 50M+ konut IP'sine AI destekli filtreleme ile erişin.

Fiyatlandırmayı GörüntüleKonut Proxy'leri
← Bloga Dön