{"id":43877,"date":"2026-08-06T09:15:17","date_gmt":"2026-08-06T06:15:17","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/"},"modified":"2026-08-06T09:15:57","modified_gmt":"2026-08-06T06:15:57","slug":"tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/","title":{"rendered":"Tweet&#8217;i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri"},"content":{"rendered":"<h2>Tweet&#8217;i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri<\/h2>\n<p>Bir tweet&#8217;i PDF olarak ar\u015fivlemek, ilk bak\u0131\u015fta sadece bir &#8220;kaydet&#8221; d\u00fc\u011fmesine basmak kadar kolay g\u00f6r\u00fcnebilir. Ancak bu basit g\u00f6r\u00fcnen i\u015flemin ard\u0131nda, web geli\u015ftiricilerinin s\u0131k\u00e7a kar\u015f\u0131la\u015ft\u0131\u011f\u0131 karma\u015f\u0131k teknik engeller yatmaktad\u0131r. Bu teknik makalede, tweet verilerini g\u00fcvenilir bir \u015fekilde PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcr\u00fcrken kar\u015f\u0131m\u0131za \u00e7\u0131kan CORS (Cross-Origin Resource Sharing) k\u0131s\u0131tlamalar\u0131, API kimlik do\u011frulama tokenlar\u0131 ve k\u00fcresel dilleri destekleyen Unicode karakter sorunlar\u0131 gibi temel zorluklar\u0131 derinlemesine inceleyece\u011fiz. Geli\u015ftiricilerin bu engelleri nas\u0131l a\u015fabilece\u011fini ad\u0131m ad\u0131m a\u00e7\u0131klayarak, sa\u011flam ve g\u00fcvenilir bir \u00e7\u00f6z\u00fcm olu\u015fturman\u0131n yollar\u0131n\u0131 ke\u015ffedece\u011fiz.<\/p>\n<p>G\u00fcn\u00fcm\u00fcz dijital d\u00fcnyas\u0131nda, sosyal medya i\u00e7eriklerini ar\u015fivleme ihtiyac\u0131 giderek artmaktad\u0131r. Hukuki s\u00fcre\u00e7lerden akademik ara\u015ft\u0131rmalara, ki\u015fisel koleksiyonlardan gazetecilik \u00e7al\u0131\u015fmalar\u0131na kadar pek \u00e7ok alanda, bir tweet&#8217;in orijinal halini koruyarak kaydetmek b\u00fcy\u00fck \u00f6nem ta\u015f\u0131r. Ancak taray\u0131c\u0131lar\u0131n g\u00fcvenlik mekanizmalar\u0131, platformlar\u0131n API politikalar\u0131 ve karakter setlerinin \u00e7e\u015fitlili\u011fi gibi fakt\u00f6rler, bu s\u00fcreci beklenenden \u00e7ok daha karma\u015f\u0131k hale getirmektedir. Bu makale boyunca, bu zorluklar\u0131n \u00fcstesinden gelmek i\u00e7in hangi y\u00f6ntemlerin kullan\u0131labilece\u011fini ve en iyi uygulamalar\u0131n neler oldu\u011funu detayl\u0131 bir \u015fekilde ele alaca\u011f\u0131z.<\/p>\n<h2>Temel Engelleri Anlamak: CORS, Tokenlar ve Unicode<\/h2>\n<p>Tweet&#8217;leri PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrme s\u00fcrecinin neden bu kadar zor oldu\u011funu anlamak i\u00e7in, \u00f6ncelikle kar\u015f\u0131m\u0131za \u00e7\u0131kan temel teknik engelleri kavramam\u0131z gerekmektedir. Bu engeller genellikle web g\u00fcvenli\u011fi, veri eri\u015fimi ve uluslararas\u0131la\u015fma (internationalization) prensipleri etraf\u0131nda \u015fekillenir. Her biri, PDF \u00e7\u0131kt\u0131s\u0131n\u0131n do\u011frulu\u011funu ve eksiksizli\u011fini do\u011frudan etkileyen kritik unsurlard\u0131r.<\/p>\n<h3>CORS Nedir ve Tweet Kaydetmeyi Nas\u0131l Etkiler?<\/h3>\n<p>CORS (Cross-Origin Resource Sharing), taray\u0131c\u0131lar\u0131n farkl\u0131 bir alan ad\u0131ndan (domain), protokolden veya porttan kaynak (resim, font, script vb.) y\u00fcklemesini k\u0131s\u0131tlayan bir g\u00fcvenlik mekanizmas\u0131d\u0131r. Bu, &#8220;Same-Origin Policy&#8221; (Ayn\u0131 Kaynak Politikas\u0131) ad\u0131 verilen daha geni\u015f bir g\u00fcvenlik kural\u0131n\u0131n bir uzant\u0131s\u0131d\u0131r. \u00d6rne\u011fin, siz bir web sayfas\u0131nda tweet&#8217;i g\u00f6r\u00fcnt\u00fcleyip PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrmeye \u00e7al\u0131\u015f\u0131rken, tweet&#8217;in i\u00e7indeki profil resimleri, ekli g\u00f6rseller veya videolar genellikle Twitter&#8217;\u0131n kendi CDN&#8217;lerinden (\u0130\u00e7erik Da\u011f\u0131t\u0131m A\u011f\u0131) y\u00fcklenir. E\u011fer sizin PDF olu\u015fturma uygulaman\u0131z farkl\u0131 bir alan ad\u0131nda \u00e7al\u0131\u015f\u0131yorsa, taray\u0131c\u0131 bu resimleri do\u011frudan \u00e7ekmenize izin vermez. Bu durum, PDF&#8217;inizin eksik veya bozuk g\u00f6rsellerle sonu\u00e7lanmas\u0131na neden olur. Geli\u015ftiriciler i\u00e7in bu, genellikle bo\u015f kutucuklar veya hata mesajlar\u0131yla dolu bir PDF anlam\u0131na gelir ve nihai \u00e7\u0131kt\u0131n\u0131n kalitesini ciddi \u015fekilde d\u00fc\u015f\u00fcr\u00fcr.<\/p>\n<h3>API Tokenlar\u0131 ve Kimlik Do\u011frulama S\u00fcre\u00e7leri Neden \u00d6nemli?<\/h3>\n<p>Twitter gibi platformlar, verilerine kontroll\u00fc eri\u015fim sa\u011flamak i\u00e7in API&#8217;lar (Uygulama Programlama Aray\u00fczleri) kullan\u0131r. Bu API&#8217;lara eri\u015fim genellikle bir kimlik do\u011frulama (authentication) s\u00fcreci gerektirir ve bu s\u00fcre\u00e7te &#8220;token&#8221; ad\u0131 verilen \u00f6zel anahtarlar kullan\u0131l\u0131r. Tokenlar, uygulaman\u0131z\u0131n Twitter sunucular\u0131na &#8220;Ben yetkili bir uygulamay\u0131m ve bu verilere eri\u015febilirim&#8221; demesinin bir yoludur. Tweet&#8217;in metnini, yazar\u0131n\u0131, zaman damgas\u0131n\u0131 veya etkile\u015fim say\u0131lar\u0131n\u0131 programatik olarak almak istedi\u011finizde, Twitter API&#8217;sine do\u011fru tokenlarla bir istek g\u00f6ndermeniz gerekir. Tokenlar olmadan veya yanl\u0131\u015f tokenlarla yap\u0131lan istekler genellikle reddedilir ve bu da tweet verilerine eri\u015fimin engellenmesi anlam\u0131na gelir. Ayr\u0131ca, API&#8217;lar\u0131n kullan\u0131m limitleri (rate limits) bulunur; belirli bir zaman diliminde yapabilece\u011finiz istek say\u0131s\u0131 k\u0131s\u0131tl\u0131d\u0131r. Bu durum, \u00f6zellikle \u00e7ok say\u0131da tweet&#8217;i PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrmeniz gerekti\u011finde ek bir zorluk te\u015fkil eder.<\/p>\n<h3>Unicode ve Karakter Seti Zorluklar\u0131 Nelerdir?<\/h3>\n<p>Tweet&#8217;ler, d\u00fcnyan\u0131n d\u00f6rt bir yan\u0131ndan farkl\u0131 dillerde ve \u00e7e\u015fitli \u00f6zel karakterlerle yaz\u0131l\u0131r. Latin alfabesi d\u0131\u015f\u0131ndaki diller (Arap\u00e7a, Japonca, \u00c7ince, Kiril vb.), emojiler ve \u00f6zel semboller, &#8220;Unicode&#8221; ad\u0131 verilen uluslararas\u0131 bir karakter kodlama standard\u0131 sayesinde g\u00f6r\u00fcnt\u00fclenebilir. PDF olu\u015fturma s\u00fcreci s\u0131ras\u0131nda, kullan\u0131lan fontlar\u0131n ve PDF k\u00fct\u00fcphanesinin bu Unicode karakterleri do\u011fru bir \u015fekilde desteklemesi ve i\u015flemesi kritik \u00f6neme sahiptir. E\u011fer PDF olu\u015fturucu, tweet&#8217;teki bir karakteri destekleyen bir fonta sahip de\u011filse veya karakter kodlamas\u0131n\u0131 yanl\u0131\u015f yorumlarsa, o karakterler PDF&#8217;te bo\u015f kutucuklar, soru i\u015faretleri veya tamamen yanl\u0131\u015f semboller olarak g\u00f6r\u00fcnecektir. Bu durum, tweet&#8217;in orijinal i\u00e7eri\u011finin bozulmas\u0131na ve okunabilirli\u011finin kaybolmas\u0131na yol a\u00e7ar. \u00d6zellikle \u00e7ok dilli tweet&#8217;leri ar\u015fivlerken bu sorunla s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131l\u0131r ve eksiksiz bir PDF i\u00e7in do\u011fru font y\u00f6netimi vazge\u00e7ilmezdir.<\/p>\n<h2>Tweet Verisini Elde Etme Y\u00f6ntemleri ve Zorluklar\u0131<\/h2>\n<p>Bir tweet&#8217;i PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrmenin ilk ad\u0131m\u0131, elbette tweet&#8217;in kendisinin ve ilgili verilerinin elde edilmesidir. Bu s\u00fcre\u00e7te iki ana yakla\u015f\u0131m \u00f6ne \u00e7\u0131kar: Twitter&#8217;\u0131n resmi API&#8217;sini kullanmak veya web kaz\u0131ma (web scraping) y\u00f6ntemlerine ba\u015fvurmak. Her iki y\u00f6ntemin de kendine \u00f6zg\u00fc avantajlar\u0131, dezavantajlar\u0131 ve beraberinde getirdi\u011fi teknik zorluklar bulunmaktad\u0131r.<\/p>\n<h3>Twitter API Kullanarak Veri \u00c7ekme Nas\u0131l Yap\u0131l\u0131r?<\/h3>\n<p>Twitter API&#8217;si, tweet&#8217;lere ve di\u011fer Twitter verilerine programatik olarak eri\u015fmek i\u00e7in en resmi ve g\u00fcvenilir yoldur. Geli\u015ftiriciler, Twitter&#8217;\u0131n sa\u011flad\u0131\u011f\u0131 API u\u00e7 noktalar\u0131n\u0131 (endpoints) kullanarak tweet&#8217;in metnini, yazar\u0131n\u0131, zaman damgas\u0131n\u0131, etkile\u015fim say\u0131lar\u0131n\u0131 (be\u011feni, retweet) ve hatta medya URL&#8217;lerini yap\u0131land\u0131r\u0131lm\u0131\u015f bir formatta (genellikle JSON) alabilirler. Bu y\u00f6ntem, verilerin tutarl\u0131 ve do\u011fru olmas\u0131n\u0131 sa\u011flar. Ancak, API&#8217;ye eri\u015fim i\u00e7in bir geli\u015ftirici hesab\u0131 olu\u015fturman\u0131z, bir uygulama kaydetmeniz ve kimlik do\u011frulama anahtarlar\u0131 (API key, API secret, access token) alman\u0131z gerekmektedir. Twitter API v2, daha modern bir yap\u0131ya sahip olup OAuth 2.0 Bearer Token kimlik do\u011frulamas\u0131n\u0131 kullan\u0131r ve belirli kullan\u0131m katmanlar\u0131na (tier) g\u00f6re farkl\u0131 eri\u015fim seviyeleri sunar. \u00d6rne\u011fin, bir tweet&#8217;in verisini \u00e7ekmek i\u00e7in JavaScript&#8217;te a\u015fa\u011f\u0131daki gibi bir kod blo\u011fu kullanabilirsiniz:<\/p>\n<div class=\"code-container\">\n<pre><code>\/\/ JavaScript ile temel bir fetch iste\u011fi\nasync function getTweetData(tweetId) {\n  const bearerToken = 'YOUR_BEARER_TOKEN'; \/\/ Kendi token\u0131n\u0131z\u0131 buraya ekleyin\n  try {\n    const response = await fetch(<code>https:\/\/api.twitter.com\/2\/tweets\/${tweetId}?tweet.fields=created_at,author_id,public_metrics&amp;expansions=author_id<\/code>, {\n      headers: {\n        'Authorization': <code>Bearer ${bearerToken}<\/code>\n      }\n    });\n\n    if (!response.ok) {\n      const errorData = await response.json();\n      throw new Error(<code>HTTP error! Status: ${response.status}, Details: ${JSON.stringify(errorData)}<\/code>);\n    }\n\n    const data = await response.json();\n    console.log(\"Tweet Verisi:\", data);\n    return data;\n  } catch (error) {\n    console.error(\"Tweet verisi \u00e7ekilirken bir hata olu\u015ftu:\", error);\n    return null;\n  }\n}\n\n\/\/ \u00d6rnek kullan\u0131m:\n\/\/ getTweetData('1460323737035677698'); \/\/ Bir tweet ID'si ile \u00e7a\u011f\u0131r\u0131n\n<\/code><\/pre>\n<\/div>\n<p>Bu y\u00f6ntem, tweet&#8217;in i\u00e7eri\u011fine do\u011frudan eri\u015fim sa\u011flad\u0131\u011f\u0131 i\u00e7in PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrme s\u00fcrecinde daha fazla kontrol sunar. Ancak API&#8217;lar\u0131n kullan\u0131m limitleri, \u00f6zellikle b\u00fcy\u00fck \u00f6l\u00e7ekli ar\u015fivleme projelerinde \u00f6nemli bir k\u0131s\u0131tlama olabilir. Ayr\u0131ca, Twitter API&#8217;sinin \u00fccretsiz katman\u0131nda eri\u015filebilen veri miktar\u0131 ve t\u00fcr\u00fc s\u0131n\u0131rl\u0131 olabilir, bu da baz\u0131 medya t\u00fcrlerini veya eski tweet&#8217;leri \u00e7ekmeyi zorla\u015ft\u0131rabilir.<\/p>\n<h3>Web Kaz\u0131ma (Web Scraping) ile Tweet Bilgisi Toplama: Alternatif Bir Yakla\u015f\u0131m m\u0131?<\/h3>\n<p>Twitter API&#8217;sine eri\u015fim zorluklar\u0131 veya k\u0131s\u0131tlamalar\u0131 nedeniyle baz\u0131 geli\u015ftiriciler web kaz\u0131ma (web scraping) y\u00f6ntemlerine y\u00f6nelebilir. Bu yakla\u015f\u0131m, bir tweet&#8217;in web sayfas\u0131n\u0131 otomatik olarak ziyaret ederek HTML i\u00e7eri\u011fini ayr\u0131\u015ft\u0131rmay\u0131 ve gerekli bilgileri (metin, resim URL&#8217;leri, kullan\u0131c\u0131 ad\u0131 vb.) \u00e7\u0131karmay\u0131 i\u00e7erir. Web kaz\u0131ma, taray\u0131c\u0131 tabanl\u0131 otomasyon ara\u00e7lar\u0131 (\u00f6rne\u011fin, Node.js i\u00e7in Puppeteer veya Python i\u00e7in Selenium) kullan\u0131larak ger\u00e7ekle\u015ftirilebilir. Bu ara\u00e7lar, ger\u00e7ek bir taray\u0131c\u0131y\u0131 programatik olarak kontrol ederek sayfan\u0131n y\u00fcklenmesini, JavaScript&#8217;in \u00e7al\u0131\u015ft\u0131r\u0131lmas\u0131n\u0131 ve hatta ekran g\u00f6r\u00fcnt\u00fcs\u00fc al\u0131nmas\u0131n\u0131 sa\u011flar. Avantaj\u0131, API anahtarlar\u0131na ihtiya\u00e7 duymadan tweet&#8217;in g\u00f6rsel d\u00fczenini ve t\u00fcm medya \u00f6\u011felerini (CORS k\u0131s\u0131tlamalar\u0131na tak\u0131lmadan) yakalayabilmesidir.<\/p>\n<p>Ancak web kaz\u0131ma, ciddi dezavantajlara sahiptir. Twitter&#8217;\u0131n kullan\u0131c\u0131 aray\u00fcz\u00fcnde (UI) yap\u0131lacak en k\u00fc\u00e7\u00fck bir de\u011fi\u015fiklik bile kaz\u0131ma beti\u011finizin bozulmas\u0131na neden olabilir. Bu y\u00f6ntem API&#8217;ye g\u00f6re daha yava\u015f ve daha fazla kaynak t\u00fcketir. Ayr\u0131ca, Twitter&#8217;\u0131n kullan\u0131m ko\u015fullar\u0131na ayk\u0131r\u0131 olabilir ve etik\/yasal sorunlara yol a\u00e7abilir. \u00d6zellikle b\u00fcy\u00fck \u00f6l\u00e7ekli veri toplama i\u00e7in \u00f6nerilmez. Genellikle, bir tweet&#8217;in sadece g\u00f6rsel bir kopyas\u0131n\u0131 almak veya \u00e7ok \u00f6zel bir d\u00fczeni yakalamak gerekti\u011finde ba\u015fvurulan bir y\u00f6ntemdir. \u00d6rne\u011fin, Puppeteer ile bir tweet sayfas\u0131n\u0131n PDF&#8217;ini do\u011frudan almak, asl\u0131nda bir ekran g\u00f6r\u00fcnt\u00fcs\u00fc al\u0131p bunu PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrmeye benzer bir yakla\u015f\u0131md\u0131r:<\/p>\n<div class=\"code-container\">\n<pre><code>\/\/ Node.js ile Puppeteer kullanarak tweet sayfas\u0131n\u0131 PDF'e d\u00f6n\u00fc\u015ft\u00fcrme\nconst puppeteer = require('puppeteer');\n\nasync function saveTweetAsPdf(tweetUrl, outputPath) {\n  const browser = await puppeteer.launch();\n  const page = await browser.newPage();\n  await page.goto(tweetUrl, { waitUntil: 'networkidle2' }); \/\/ Sayfan\u0131n tamamen y\u00fcklenmesini bekleyin\n\n  \/\/ Twitter'\u0131n giri\u015f yapma penceresi veya \u00e7erez onay\u0131 gibi pop-up'lar\u0131 kapatma\n  \/\/ Bu k\u0131s\u0131m Twitter UI de\u011fi\u015fikliklerine g\u00f6re g\u00fcncellenmelidir\n  const closeButtonSelector = 'div[aria-label=\"Kapat\"]'; \/\/ \u00d6rnek bir kapatma butonu se\u00e7icisi\n  const closeButton = await page.$(closeButtonSelector);\n  if (closeButton) {\n    await closeButton.click();\n    await page.waitForTimeout(500); \/\/ Kapanmas\u0131 i\u00e7in biraz bekleyin\n  }\n\n  await page.pdf({\n    path: outputPath,\n    format: 'A4',\n    printBackground: true \/\/ Arka plan renklerini ve resimlerini dahil et\n  });\n\n  await browser.close();\n  console.log(<code>Tweet PDF olarak kaydedildi: ${outputPath}<\/code>);\n}\n\n\/\/ \u00d6rnek kullan\u0131m:\n\/\/ saveTweetAsPdf('https:\/\/twitter.com\/TwitterDev\/status\/1460323737035677698', 'tweet.pdf');\n<\/code><\/pre>\n<\/div>\n<p>Bu kod blo\u011fu, Puppeteer&#8217;\u0131n g\u00fcc\u00fcn\u00fc g\u00f6sterse de, Twitter&#8217;\u0131n dinamik yap\u0131s\u0131 ve s\u00fcrekli de\u011fi\u015fen aray\u00fcz\u00fc nedeniyle bak\u0131m\u0131 zordur. Bu nedenle, API&#8217;ler genellikle daha istikrarl\u0131 ve s\u00fcrd\u00fcr\u00fclebilir bir \u00e7\u00f6z\u00fcm sunar.<\/p>\n<h2>PDF Olu\u015fturma S\u00fcre\u00e7leri ve Teknik \u00c7\u00f6z\u00fcmler<\/h2>\n<p>Tweet verilerini ba\u015far\u0131yla elde ettikten sonraki a\u015fama, bu verileri estetik ve do\u011fru bir \u015fekilde PDF format\u0131na d\u00f6n\u00fc\u015ft\u00fcrmektir. Bu s\u00fcre\u00e7, genellikle taray\u0131c\u0131 taraf\u0131nda (client-side) veya sunucu taraf\u0131nda (server-side) ger\u00e7ekle\u015ftirilebilir ve her yakla\u015f\u0131m\u0131n kendine \u00f6zg\u00fc avantajlar\u0131 ve zorluklar\u0131 bulunmaktad\u0131r. \u00d6zellikle daha \u00f6nce bahsetti\u011fimiz CORS k\u0131s\u0131tlamalar\u0131, bu a\u015famada kar\u015f\u0131m\u0131za b\u00fcy\u00fck bir engel olarak \u00e7\u0131kabilir.<\/p>\n<h3>Taray\u0131c\u0131 Taraf\u0131nda PDF Olu\u015fturma: <code>html2canvas<\/code> ve <code>jsPDF<\/code><\/h3>\n<p>Taray\u0131c\u0131 taraf\u0131nda PDF olu\u015fturma, kullan\u0131c\u0131n\u0131n taray\u0131c\u0131s\u0131nda \u00e7al\u0131\u015fan JavaScript k\u00fct\u00fcphaneleri arac\u0131l\u0131\u011f\u0131yla ger\u00e7ekle\u015ftirilir. Bu yakla\u015f\u0131m\u0131n en pop\u00fcler kombinasyonlar\u0131ndan biri <code>html2canvas<\/code> ve <code>jsPDF<\/code>&#8216;tir. <code>html2canvas<\/code> k\u00fct\u00fcphanesi, bir HTML elementini (\u00f6rne\u011fin, bir tweet&#8217;i i\u00e7eren bir <code>div<\/code>) al\u0131p onu bir tuval (canvas) elementine \u00e7izer, yani asl\u0131nda bir resme d\u00f6n\u00fc\u015ft\u00fcr\u00fcr. Daha sonra <code>jsPDF<\/code> k\u00fct\u00fcphanesi, bu tuval g\u00f6r\u00fcnt\u00fcs\u00fcn\u00fc alarak bir PDF belgesi olu\u015fturur ve kullan\u0131c\u0131n\u0131n indirmesi i\u00e7in sunar.<\/p>\n<p>Bu y\u00f6ntem, sunucu y\u00fck\u00fcn\u00fc azaltmas\u0131 ve h\u0131zl\u0131 bir kullan\u0131c\u0131 deneyimi sunmas\u0131 a\u00e7\u0131s\u0131ndan caziptir. Ancak <code>html2canvas<\/code>, CORS k\u0131s\u0131tlamalar\u0131 nedeniyle farkl\u0131 bir kaynaktan gelen resimleri (\u00f6rne\u011fin, Twitter&#8217;\u0131n CDN&#8217;inden gelen profil resimleri veya ekli g\u00f6rseller) do\u011frudan tuvale \u00e7izemez. E\u011fer bu resimler i\u00e7in \u00f6zel bir proxy ayarlanmam\u0131\u015fsa, genellikle tuvale \u00e7izilemezler ve PDF \u00e7\u0131kt\u0131s\u0131nda eksik veya bo\u015f olarak g\u00f6r\u00fcn\u00fcrler. Bu, \u00f6zellikle tweet&#8217;lerin g\u00f6rsel zenginli\u011fini korumak isteyen kullan\u0131c\u0131lar i\u00e7in b\u00fcy\u00fck bir sorundur. Ayr\u0131ca, <code>html2canvas<\/code> karma\u015f\u0131k CSS stillerini veya SVG&#8217;leri her zaman m\u00fckemmel bir \u015fekilde i\u015fleyemeyebilir, bu da g\u00f6rsel do\u011frulukta sapmalara yol a\u00e7abilir.<\/p>\n<div class=\"code-container\">\n<pre><code>&lt;!-- HTML Yap\u0131s\u0131 --&gt;\n&lt;div id=\"tweet-container\" style=\"border: 1px solid #eee; padding: 15px; max-width: 500px;\"&gt;\n  &lt;p&gt;&lt;strong&gt;@KullaniciAdi&lt;\/strong&gt;&lt;\/p&gt;\n  &lt;p&gt;Bu bir \u00f6rnek tweet metnidir. \u0130\u00e7erisinde &lt;span style=\"color: blue;\"&gt;etiketler&lt;\/span&gt; ve &lt;span style=\"font-family: 'Segoe UI Emoji';\"&gt;\ud83d\ude80\u2728&lt;\/span&gt; emojileri bulunabilir.&lt;\/p&gt;\n  &lt;img src=\"https:\/\/via.placeholder.com\/150\" alt=\"\u00d6rnek Resim\" style=\"max-width: 100%; display: block; margin-top: 10px;\"&gt;\n  &lt;small&gt;2023-10-27 14:30&lt;\/small&gt;\n&lt;\/div&gt;\n&lt;button onclick=\"saveTweetAsPdfClient()\"&gt;PDF Olarak Kaydet (Taray\u0131c\u0131)&lt;\/button&gt;\n\n&lt;script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/html2canvas\/1.4.1\/html2canvas.min.js\"&gt;&lt;\/script&gt;\n&lt;script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf\/2.5.1\/jspdf.umd.min.js\"&gt;&lt;\/script&gt;\n&lt;script&gt;\n  function saveTweetAsPdfClient() {\n    const input = document.getElementById('tweet-container');\n    html2canvas(input, {\n      useCORS: true, \/\/ CORS ile ilgili sorunlar\u0131 \u00e7\u00f6zmek i\u00e7in proxy kullan\u0131l\u0131yorsa\n      allowTaint: true \/\/ G\u00fcvenilmeyen kaynaklardan gelen i\u00e7eri\u011fe izin verir, g\u00fcvenlik riski ta\u015f\u0131yabilir\n    }).then((canvas) => {\n      const imgData = canvas.toDataURL('image\/png');\n      const { jsPDF } = window.jspdf;\n      const pdf = new jsPDF('p', 'mm', 'a4');\n      const imgWidth = 210; \/\/ A4 geni\u015fli\u011fi\n      const pageHeight = 297; \/\/ A4 y\u00fcksekli\u011fi\n      const imgHeight = canvas.height * imgWidth \/ canvas.width;\n      let heightLeft = imgHeight;\n      let position = 0;\n\n      pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);\n      heightLeft -= pageHeight;\n\n      while (heightLeft >= 0) {\n        position = heightLeft - imgHeight;\n        pdf.addPage();\n        pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);\n        heightLeft -= pageHeight;\n      }\n      pdf.save(\"tweet.pdf\");\n    });\n  }\n&lt;\/script&gt;\n<\/code><\/pre>\n<\/div>\n<p>Yukar\u0131daki \u00f6rnekte <code>useCORS: true<\/code> parametresi, <code>html2canvas<\/code>&#8216;\u0131n CORS proxy&#8217;si kullan\u0131larak d\u0131\u015f kaynaklar\u0131 \u00e7ekmeye \u00e7al\u0131\u015faca\u011f\u0131n\u0131 belirtir, ancak bu sadece sunucunuzda uygun bir proxy yap\u0131land\u0131rmas\u0131 varsa i\u015fe yarar.<\/p>\n<h3>Sunucu Taraf\u0131nda PDF Olu\u015fturma: Kontrol\u00fc Ele Almak<\/h3>\n<p>Sunucu taraf\u0131nda PDF olu\u015fturma, genellikle daha g\u00fcvenilir ve esnek bir \u00e7\u00f6z\u00fcmd\u00fcr. Bu yakla\u015f\u0131mda, bir web sunucusu (Node.js, Python, PHP vb.) bir tweet&#8217;in HTML&#8217;ini veya verilerini al\u0131r ve bir PDF olu\u015fturma arac\u0131 kullanarak bunu bir PDF dosyas\u0131na d\u00f6n\u00fc\u015ft\u00fcr\u00fcr. Bu y\u00f6ntem, taray\u0131c\u0131 tabanl\u0131 CORS k\u0131s\u0131tlamalar\u0131n\u0131 a\u015fma, \u00f6zel fontlar\u0131 g\u00f6mme ve daha karma\u015f\u0131k d\u00fczenleri do\u011fru bir \u015fekilde i\u015fleme yetene\u011fi sunar.<\/p>\n<p>Pop\u00fcler sunucu taraf\u0131 ara\u00e7lar\u0131 aras\u0131nda Node.js i\u00e7in <a href=\"https:\/\/pptr.dev\/\">Puppeteer<\/a> (headless Chrome&#8217;u kontrol eder), Python i\u00e7in <a href=\"https:\/\/wkhtmltopdf.org\/\">wkhtmltopdf<\/a> veya <a href=\"https:\/\/pypi.org\/project\/xhtml2pdf\/\">xhtml2pdf<\/a> gibi k\u00fct\u00fcphaneler bulunur. Puppeteer, bir Chrome taray\u0131c\u0131s\u0131n\u0131 ba\u015fs\u0131z (headless) modda \u00e7al\u0131\u015ft\u0131rarak bir web sayfas\u0131n\u0131 ziyaret etmesini, ekran g\u00f6r\u00fcnt\u00fcs\u00fc almas\u0131n\u0131 veya do\u011frudan PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrmesini sa\u011flar. Bu, tweet&#8217;in web sayfas\u0131n\u0131n tam olarak g\u00f6r\u00fcnd\u00fc\u011f\u00fc gibi PDF&#8217;e aktar\u0131lmas\u0131na olanak tan\u0131r ve CORS k\u0131s\u0131tlamalar\u0131 taray\u0131c\u0131 ortam\u0131nda de\u011fil, sunucu ortam\u0131nda a\u015f\u0131ld\u0131\u011f\u0131 i\u00e7in sorun olmaktan \u00e7\u0131kar. Ayr\u0131ca, Puppeteer gibi ara\u00e7lar, sayfa y\u00fcklenmeden \u00f6nce JavaScript kodlar\u0131n\u0131 \u00e7al\u0131\u015ft\u0131rabilir, bu da dinamik olarak y\u00fcklenen tweet i\u00e7eriklerini yakalamak i\u00e7in idealdir.<\/p>\n<div class=\"code-container\">\n<pre><code>\/\/ Node.js ile Puppeteer kullanarak sunucu taraf\u0131nda PDF olu\u015fturma\n\/\/ Bu kodun \u00e7al\u0131\u015fmas\u0131 i\u00e7in 'puppeteer' paketini kurman\u0131z gerekir: npm install puppeteer\nconst puppeteer = require('puppeteer');\nconst express = require('express');\nconst app = express();\nconst port = 3000;\n\napp.get('\/save-tweet-pdf', async (req, res) => {\n  const tweetUrl = req.query.url; \/\/ Kullan\u0131c\u0131dan tweet URL'sini al\n  if (!tweetUrl) {\n    return res.status(400).send('Tweet URL\\'si gerekli.');\n  }\n\n  let browser;\n  try {\n    browser = await puppeteer.launch();\n    const page = await browser.newPage();\n\n    \/\/ Twitter'\u0131n \u00e7erez onay\u0131 veya giri\u015f yapma pop-up'lar\u0131n\u0131 ele almak i\u00e7in\n    \/\/ \u00d6nce sayfaya gidin, sonra pop-up'lar\u0131 kapatmaya \u00e7al\u0131\u015f\u0131n.\n    await page.goto(tweetUrl, { waitUntil: 'networkidle2', timeout: 60000 }); \/\/ 60 saniye bekleme s\u00fcresi\n    \n    \/\/ \u00d6rnek: Twitter'\u0131n \"Giri\u015f yap\" veya \"\u00c7erezleri kabul et\" pop-up'lar\u0131n\u0131 kapatma\n    const closeButtonSelector = 'div[aria-label=\"Kapat\"]'; \/\/ Bu se\u00e7ici de\u011fi\u015febilir\n    const closeButton = await page.$(closeButtonSelector);\n    if (closeButton) {\n      await closeButton.click();\n      await page.waitForTimeout(500); \/\/ Kapanmas\u0131 i\u00e7in k\u0131sa bir bekleme\n    }\n\n    const pdfBuffer = await page.pdf({\n      format: 'A4',\n      printBackground: true,\n      margin: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' }\n    });\n\n    res.setHeader('Content-Type', 'application\/pdf');\n    res.setHeader('Content-Disposition', 'attachment; filename=\"tweet.pdf\"');\n    res.send(pdfBuffer);\n  } catch (error) {\n    console.error('PDF olu\u015fturulurken hata:', error);\n    res.status(500).send('PDF olu\u015fturulurken bir hata olu\u015ftu.');\n  } finally {\n    if (browser) {\n      await browser.close();\n    }\n  }\n});\n\napp.listen(port, () => {\n  console.log(<code>PDF sunucusu http:\/\/localhost:${port} adresinde \u00e7al\u0131\u015f\u0131yor<\/code>);\n});\n<\/code><\/pre>\n<\/div>\n<p>Bu sunucu taraf\u0131 \u00e7\u00f6z\u00fcm, tweet&#8217;in tam g\u00f6rselini ve t\u00fcm medya \u00f6\u011felerini i\u00e7eren y\u00fcksek kaliteli bir PDF \u00e7\u0131kt\u0131s\u0131 alman\u0131z\u0131 sa\u011flar. Ancak sunucunuzda Puppeteer&#8217;\u0131 \u00e7al\u0131\u015ft\u0131rmak i\u00e7in gerekli kaynaklar\u0131n (CPU, RAM) bulunmas\u0131 ve taray\u0131c\u0131y\u0131 ba\u015flatman\u0131n getirdi\u011fi gecikmeler g\u00f6z \u00f6n\u00fcnde bulundurulmal\u0131d\u0131r.<\/p>\n<h3>CORS Engellerini A\u015fmak \u0130\u00e7in Proxy Sunucular\u0131 Nas\u0131l Kullan\u0131l\u0131r?<\/h3>\n<p>CORS, taray\u0131c\u0131lar\u0131n g\u00fcvenlik mekanizmas\u0131 oldu\u011fu i\u00e7in, taray\u0131c\u0131 d\u0131\u015f\u0131ndaki bir ortamda (yani bir sunucuda) yap\u0131lan istekler bu k\u0131s\u0131tlamalara tabi de\u011fildir. Bu prensipten yola \u00e7\u0131karak, taray\u0131c\u0131 taraf\u0131nda PDF olu\u015fturma y\u00f6ntemlerinde kar\u015f\u0131la\u015f\u0131lan CORS sorununu a\u015fmak i\u00e7in bir &#8220;proxy sunucusu&#8221; kullanabiliriz. Proxy sunucusu, uygulaman\u0131z ile Twitter&#8217;\u0131n medya sunucular\u0131 aras\u0131nda bir arac\u0131 g\u00f6revi g\u00f6r\u00fcr. Taray\u0131c\u0131n\u0131z, do\u011frudan Twitter&#8217;\u0131n resim sunucusundan resim istemek yerine, kendi proxy sunucunuza bir istek g\u00f6nderir. Proxy sunucusu bu iste\u011fi al\u0131r, Twitter&#8217;\u0131n sunucusundan resmi \u00e7eker (ki bu i\u015flem sunucu taraf\u0131nda oldu\u011fu i\u00e7in CORS&#8217;a tak\u0131lmaz) ve ard\u0131ndan resmi uygulaman\u0131za geri g\u00f6nderir. Bu sayede, taray\u0131c\u0131n\u0131z resmi kendi alan ad\u0131n\u0131zdan geliyormu\u015f gibi alg\u0131lar ve CORS k\u0131s\u0131tlamalar\u0131 devre d\u0131\u015f\u0131 kal\u0131r.<\/p>\n<p>Basit bir Node.js Express proxy sunucusu \u00f6rne\u011fi:<\/p>\n<div class=\"code-container\">\n<pre><code>\/\/ Node.js Express ile basit bir CORS proxy sunucusu\n\/\/ Bu kodun \u00e7al\u0131\u015fmas\u0131 i\u00e7in 'express' ve 'node-fetch' paketlerini kurman\u0131z gerekir: npm install express node-fetch\nconst express = require('express');\nconst fetch = require('node-fetch');\nconst app = express();\nconst port = 3001; \/\/ Farkl\u0131 bir port kullan\u0131n\n\n\/\/ T\u00fcm CORS isteklerine izin ver (g\u00fcvenlik a\u00e7\u0131s\u0131ndan dikkatli kullan\u0131lmal\u0131)\napp.use((req, res, next) => {\n  res.header('Access-Control-Allow-Origin', '*'); \/\/ T\u00fcm kaynaklardan gelen isteklere izin ver\n  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');\n  next();\n});\n\napp.get('\/proxy-image', async (req, res) => {\n  const imageUrl = req.query.url; \/\/ \u0130stemciden gelen resim URL'si\n  if (!imageUrl) {\n    return res.status(400).send('Resim URL\\'si gerekli.');\n  }\n\n  try {\n    const response = await fetch(imageUrl);\n    if (!response.ok) {\n      throw new Error(<code>Resim \u00e7ekilemedi: ${response.statusText}<\/code>);\n    }\n    const buffer = await response.buffer(); \/\/ Resmi buffer olarak al\n\n    \/\/ Resim t\u00fcr\u00fcn\u00fc orijinal yan\u0131ttan al veya varsay\u0131lan olarak ayarla\n    const contentType = response.headers.get('content-type') || 'application\/octet-stream';\n    res.setHeader('Content-Type', contentType);\n    res.send(buffer);\n  } catch (error) {\n    console.error('Proxy hatas\u0131:', error);\n    res.status(500).send('Resim proxy edilemedi.');\n  }\n});\n\napp.listen(port, () => {\n  console.log(<code>Proxy sunucusu http:\/\/localhost:${port} adresinde \u00e7al\u0131\u015f\u0131yor<\/code>);\n});\n<\/code><\/pre>\n<\/div>\n<p>Bu proxy&#8217;yi kullanarak, <code>html2canvas<\/code> k\u00fct\u00fcphanesine resim URL&#8217;lerini do\u011frudan Twitter&#8217;dan de\u011fil, kendi proxy sunucunuzdan istemesini s\u00f6yleyebilirsiniz. \u00d6rne\u011fin, <code>&lt;img src=\"https:\/\/twitter.com\/...\"&gt;<\/code> yerine <code>&lt;img src=\"http:\/\/localhost:3001\/proxy-image?url=https:\/\/twitter.com\/...\"&gt;<\/code> \u015feklinde bir yap\u0131 kullanman\u0131z gerekir. Bu, taray\u0131c\u0131 taraf\u0131nda PDF olu\u015ftururken eksik resim sorununu \u00e7\u00f6zmek i\u00e7in etkili bir y\u00f6ntemdir.<\/p>\n<h2>Unicode ve Font Y\u00f6netimi: Eksiksiz Bir PDF \u0130\u00e7in<\/h2>\n<p>Tweet&#8217;ler, d\u00fcnyan\u0131n d\u00f6rt bir yan\u0131ndan farkl\u0131 dillerde, emojilerle ve \u00f6zel karakterlerle doludur. Bu zengin karakter \u00e7e\u015fitlili\u011fini PDF&#8217;e do\u011fru bir \u015fekilde aktarmak, \u00f6zellikle Unicode ve font y\u00f6netimi konular\u0131nda dikkatli olmay\u0131 gerektirir. Aksi takdirde, PDF \u00e7\u0131kt\u0131n\u0131zda bozuk karakterler, bo\u015f kutucuklar veya anlams\u0131z sembollerle kar\u015f\u0131la\u015fabilirsiniz.<\/p>\n<p>Unicode, metin karakterlerini dijital ortamda tutarl\u0131 bir \u015fekilde temsil etmek i\u00e7in tasarlanm\u0131\u015f bir standartt\u0131r. D\u00fcnya \u00fczerindeki hemen hemen t\u00fcm yaz\u0131 sistemlerini ve sembolleri kapsar. Ancak bir PDF olu\u015fturucu, bu Unicode karakterlerini do\u011fru bir \u015fekilde g\u00f6r\u00fcnt\u00fcleyebilmek i\u00e7in uygun fontlara sahip olmal\u0131d\u0131r. \u00c7o\u011fu standart PDF fontu (\u00f6rne\u011fin, Helvetica, Times New Roman) yaln\u0131zca Latin alfabesini ve s\u0131n\u0131rl\u0131 say\u0131da \u00f6zel karakteri destekler. Bu nedenle, bir tweet Arap\u00e7a, Japonca, \u00c7ince veya Kiril alfabesi i\u00e7eriyorsa ya da yayg\u0131n olarak kullan\u0131lan modern emojiler bar\u0131nd\u0131r\u0131yorsa, bu fontlar yetersiz kalacakt\u0131r.<\/p>\n<p>Bu sorunu \u00e7\u00f6zmek i\u00e7in, PDF olu\u015fturma s\u00fcrecinde &#8220;font g\u00f6mme&#8221; (font embedding) tekni\u011fi kullan\u0131l\u0131r. Bu, PDF dosyas\u0131na, belgede kullan\u0131lan t\u00fcm veya belirli fontlar\u0131n bir alt k\u00fcmesini (subset) dahil etmek anlam\u0131na gelir. B\u00f6ylece, PDF&#8217;i a\u00e7an ki\u015finin bilgisayar\u0131nda ilgili font y\u00fckl\u00fc olmasa bile, belge i\u00e7indeki metinler do\u011fru bir \u015fekilde g\u00f6r\u00fcnt\u00fclenebilir. \u00d6zellikle Google&#8217;\u0131n <a href=\"https:\/\/fonts.google.com\/noto\">Noto font ailesi<\/a> gibi geni\u015f Unicode deste\u011fi sunan fontlar, bu t\u00fcr \u00e7ok dilli i\u00e7erikler i\u00e7in idealdir.<\/p>\n<p>Sunucu taraf\u0131nda Puppeteer gibi ara\u00e7lar kullan\u0131rken, Chrome taray\u0131c\u0131s\u0131n\u0131n varsay\u0131lan font deste\u011fi genellikle olduk\u00e7a iyidir ve \u00e7o\u011fu Unicode karakteri otomatik olarak i\u015fleyebilir. Ancak, <code>wkhtmltopdf<\/code> veya baz\u0131 JavaScript PDF k\u00fct\u00fcphaneleriyle \u00e7al\u0131\u015f\u0131rken, bu fontlar\u0131 manuel olarak yap\u0131land\u0131rman\u0131z veya dahil etmeniz gerekebilir. \u00d6rne\u011fin, <code>jsPDF<\/code> kullan\u0131yorsan\u0131z, \u00f6zel fontlar\u0131 PDF&#8217;e eklemek i\u00e7in ek ad\u0131mlar atman\u0131z gerekebilir. Bu, genellikle font dosyas\u0131n\u0131 (<code>.ttf<\/code> veya <code>.otf<\/code>) base64 olarak kodlay\u0131p k\u00fct\u00fcphaneye tan\u0131tarak yap\u0131l\u0131r. Bu sayede, PDF olu\u015fturma s\u0131ras\u0131nda tweet&#8217;teki t\u00fcm karakterlerin do\u011fru fontlarla e\u015fle\u015ftirilmesi ve belgede d\u00fczg\u00fcn bir \u015fekilde temsil edilmesi sa\u011flan\u0131r.<\/p>\n<p>Ek olarak, metin i\u00e7eri\u011finin ba\u015ftan sona UTF-8 (Unicode Transformation Format &#8211; 8-bit) kodlamas\u0131yla i\u015flendi\u011finden emin olmak \u00f6nemlidir. Veri \u00e7ekme a\u015famas\u0131ndan PDF&#8217;e yazma a\u015famas\u0131na kadar her ad\u0131mda UTF-8 kullanmak, karakter bozulmalar\u0131n\u0131 \u00f6nlemenin temelidir. Bu titiz font ve kodlama y\u00f6netimi sayesinde, tweet&#8217;lerinizin PDF versiyonlar\u0131, orijinal i\u00e7eri\u011fin t\u00fcm zenginli\u011fini ve do\u011frulu\u011funu koruyarak gelece\u011fe aktar\u0131labilir.<\/p>\n<h2>Vaka Analizi: Bir Hukuk B\u00fcrosunun Tweet Ar\u015fivleme \u0130htiyac\u0131<\/h2>\n<p>Ger\u00e7ek d\u00fcnyadan bir senaryo ile konuyu peki\u015ftirelim. Bir hukuk b\u00fcrosu, m\u00fcvekkili aleyhine sosyal medyada yap\u0131lan bir dizi hakaret i\u00e7eren tweet&#8217;i delil olarak kullanmak \u00fczere ar\u015fivlemesi gerekti\u011fini varsayal\u0131m. Bu tweet&#8217;lerin sadece ekran g\u00f6r\u00fcnt\u00fcs\u00fc al\u0131nmas\u0131 yeterli de\u011fildir; \u00e7\u00fcnk\u00fc ekran g\u00f6r\u00fcnt\u00fcleri kolayca manip\u00fcle edilebilir, metin olarak aranamaz ve tweet&#8217;in t\u00fcm meta verilerini (tarih, saat, yazar, be\u011feni\/retweet say\u0131s\u0131) eksiksiz sunmayabilir. Hukuk b\u00fcrosu, bu tweet&#8217;leri yasal ge\u00e7erlili\u011fi olan, aranabilir ve orijinaline sad\u0131k bir PDF format\u0131nda kaydetmek istemektedir.<\/p>\n<p>Hukuk b\u00fcrosu, bu g\u00f6revi otomatikle\u015ftirmek i\u00e7in bir geli\u015ftiriciyle anla\u015f\u0131r. Geli\u015ftirici, a\u015fa\u011f\u0131daki ad\u0131mlar\u0131 izleyerek bir \u00e7\u00f6z\u00fcm geli\u015ftirmeye ba\u015flar:<\/p>\n<ol>\n<li><strong>Veri \u00c7ekme:<\/strong> \u0130lk olarak, geli\u015ftirici Twitter API&#8217;sine ba\u015fvurur. Geli\u015ftirici hesab\u0131 a\u00e7ar, gerekli kimlik do\u011frulama anahtarlar\u0131n\u0131 al\u0131r ve ilgili tweet&#8217;lerin ID&#8217;lerini kullanarak API arac\u0131l\u0131\u011f\u0131yla metin i\u00e7eri\u011fini, yazar bilgilerini, yay\u0131nlanma tarihini ve etkile\u015fim metriklerini (<code>public_metrics<\/code>) \u00e7eker. Bu, tweet&#8217;in temel, do\u011frulanabilir metinsel verilerini sa\u011flar.<\/li>\n<li><strong>G\u00f6rsel \u0130\u00e7eri\u011fi Y\u00f6netme (CORS Sorunu):<\/strong> Tweet&#8217;lerdeki profil resimleri ve ekli g\u00f6rseller API&#8217;den do\u011frudan gelmez; URL&#8217;leri gelir. Bu URL&#8217;lerden resimleri \u00e7ekmek i\u00e7in taray\u0131c\u0131 taraf\u0131nda CORS engeliyle kar\u015f\u0131la\u015f\u0131laca\u011f\u0131 \u00f6ng\u00f6r\u00fcl\u00fcr. Geli\u015ftirici, bu engeli a\u015fmak i\u00e7in kendi sunucusunda basit bir Node.js tabanl\u0131 proxy sunucusu kurar. Bu proxy, Twitter&#8217;\u0131n CDN&#8217;lerinden resimleri \u00e7eker ve kendi alan ad\u0131ndan uygulaman\u0131n kullan\u0131m\u0131na sunar.<\/li>\n<li><strong>HTML Olu\u015fturma:<\/strong> \u00c7ekilen metin verileri ve proxy \u00fczerinden al\u0131nan g\u00f6rsel URL&#8217;leri kullan\u0131larak, her bir tweet i\u00e7in HTML \u015fablonlar\u0131 olu\u015fturulur. Bu \u015fablonlar, tweet&#8217;in Twitter&#8217;daki orijinal g\u00f6r\u00fcn\u00fcm\u00fcn\u00fc taklit edecek \u015fekilde tasarlan\u0131r.<\/li>\n<li><strong>PDF D\u00f6n\u00fc\u015ft\u00fcrme (Unicode ve Fontlar):<\/strong> Olu\u015fturulan HTML&#8217;i PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrmek i\u00e7in sunucu taraf\u0131nda Puppeteer kullan\u0131l\u0131r. Puppeteer, headless Chrome&#8217;u \u00e7al\u0131\u015ft\u0131rarak bu HTML \u015fablonlar\u0131n\u0131 sanal bir taray\u0131c\u0131da render eder. Bu sayede, taray\u0131c\u0131 ortam\u0131n\u0131n t\u00fcm CSS ve JavaScript i\u015fleme yetenekleri kullan\u0131l\u0131r. \u00d6zellikle, Puppeteer&#8217;\u0131n kulland\u0131\u011f\u0131 Chrome taray\u0131c\u0131s\u0131, geni\u015f Unicode font deste\u011fi sayesinde farkl\u0131 dillerdeki karakterleri ve emojileri do\u011fru bir \u015fekilde i\u015fler. Geli\u015ftirici, PDF \u00e7\u0131kt\u0131s\u0131n\u0131n kalitesini art\u0131rmak i\u00e7in Puppeteer&#8217;\u0131n <code>page.pdf()<\/code> fonksiyonunu kullanarak sayfa kenarl\u0131klar\u0131, arka plan renkleri ve bask\u0131 kalitesi gibi ayarlar\u0131 optimize eder.<\/li>\n<li><strong>Meta Veri Ekleme:<\/strong> Olu\u015fturulan PDF&#8217;e, tweet&#8217;in API&#8217;den \u00e7ekilen do\u011frulanm\u0131\u015f zaman damgas\u0131 ve yazar bilgileri gibi meta veriler de eklenir. Bu, PDF&#8217;in yasal delil olarak g\u00fcvenilirli\u011fini art\u0131r\u0131r.<\/li>\n<\/ol>\n<p>Bu \u00e7ok ad\u0131ml\u0131 ve katmanl\u0131 yakla\u015f\u0131m sayesinde hukuk b\u00fcrosu, her bir tweet&#8217;i hem g\u00f6rsel olarak orijinaline sad\u0131k hem de metinsel olarak aranabilir, eksiksiz ve do\u011frulanabilir bir PDF dosyas\u0131 olarak ar\u015fivleyebilmi\u015ftir. Bu vaka analizi, &#8220;bir tweet&#8217;i PDF&#8217;e kaydetmenin neden bu kadar zor oldu\u011funu&#8221; ve bu zorluklar\u0131n \u00fcstesinden gelmek i\u00e7in entegre bir teknik \u00e7\u00f6z\u00fcm\u00fcn nas\u0131l geli\u015ftirilebilece\u011fini a\u00e7\u0131k\u00e7a ortaya koymaktad\u0131r.<\/p>\n<h2>\u0130leri D\u00fczey \u0130pu\u00e7lar\u0131 ve Optimizasyonlar<\/h2>\n<p>Tweet&#8217;leri PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrme s\u00fcrecini daha da sa\u011flam, verimli ve kullan\u0131c\u0131 dostu hale getirmek i\u00e7in baz\u0131 ileri d\u00fczey ipu\u00e7lar\u0131 ve optimizasyonlar bulunmaktad\u0131r. Bu y\u00f6ntemler, \u00f6zellikle b\u00fcy\u00fck \u00f6l\u00e7ekli ar\u015fivleme projelerinde veya y\u00fcksek performans gerektiren uygulamalarda fark yaratabilir.<\/p>\n<h3>API \u00c7a\u011fr\u0131lar\u0131n\u0131 \u00d6nbelle\u011fe Alma (Caching) Nas\u0131l Yap\u0131l\u0131r?<\/h3>\n<p>Twitter API&#8217;sinin kullan\u0131m limitleri (rate limits) g\u00f6z \u00f6n\u00fcne al\u0131nd\u0131\u011f\u0131nda, ayn\u0131 tweet verisini tekrar tekrar \u00e7ekmek hem gereksiz gecikmelere yol a\u00e7ar hem de limitlerinize daha h\u0131zl\u0131 ula\u015fman\u0131za neden olur. Bu sorunu a\u015fmak i\u00e7in &#8220;\u00f6nbelle\u011fe alma&#8221; (caching) stratejileri kullan\u0131labilir. \u00c7ekilen tweet verilerini bir veritaban\u0131nda (SQL, NoSQL) veya bir bellek i\u00e7i \u00f6nbellek sisteminde (Redis, Memcached) saklayabilirsiniz. Bir tweet&#8217;in verisine ihtiya\u00e7 duyuldu\u011funda, \u00f6nce \u00f6nbellekte arama yap\u0131l\u0131r. E\u011fer veri \u00f6nbellekte mevcutsa, do\u011frudan oradan al\u0131n\u0131r; de\u011filse, API&#8217;den \u00e7ekilir ve ard\u0131ndan \u00f6nbelle\u011fe kaydedilir. Bu y\u00f6ntem, API \u00e7a\u011fr\u0131lar\u0131n\u0131n say\u0131s\u0131n\u0131 \u00f6nemli \u00f6l\u00e7\u00fcde azalt\u0131r, uygulaman\u0131n performans\u0131n\u0131 art\u0131r\u0131r ve API limitlerine tak\u0131lma riskini minimize eder. \u00d6nbelle\u011fe al\u0131nan verilerin ne kadar s\u00fcreyle ge\u00e7erli olaca\u011f\u0131n\u0131 (TTL &#8211; Time To Live) belirlemek de \u00f6nemlidir, b\u00f6ylece verilerin g\u00fcncelli\u011fi korunur.<\/p>\n<h3>Uzun Tweet Dizilerini (Thread) Y\u00f6netmek \u0130\u00e7in Stratejiler Nelerdir?<\/h3>\n<p>Modern Twitter kullan\u0131m\u0131yla birlikte, &#8220;tweet dizileri&#8221; veya &#8220;thread&#8217;ler&#8221; olduk\u00e7a yayg\u0131n hale gelmi\u015ftir. Bir diziyi tek bir PDF olarak kaydetmek, ek zorluklar getirir. Twitter API&#8217;si, bir tweet&#8217;in yan\u0131tlar\u0131n\u0131 veya bir dizideki sonraki tweet&#8217;leri almak i\u00e7in ilgili u\u00e7 noktalar sunar. Geli\u015ftirici, ba\u015flang\u0131\u00e7 tweet&#8217;inin ID&#8217;sinden yola \u00e7\u0131karak, dizideki t\u00fcm tweet&#8217;leri s\u0131rayla \u00e7ekecek \u00f6zyinelemeli (recursive) veya yinelemeli (iterative) API \u00e7a\u011fr\u0131lar\u0131 yapmal\u0131d\u0131r. Bu tweet&#8217;ler \u00e7ekildikten sonra, do\u011fru s\u0131rayla bir araya getirilerek tek bir HTML belgesi olu\u015fturulmal\u0131d\u0131r. PDF d\u00f6n\u00fc\u015ft\u00fcrme a\u015famas\u0131nda, bu uzun HTML belgesinin tek bir PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcr\u00fclmesi, sayfa sonlar\u0131 (page breaks) ve d\u00fczenin bozulmamas\u0131 i\u00e7in \u00f6zel CSS kurallar\u0131 (<code>page-break-after: always;<\/code> gibi) gerektirebilir. Puppeteer gibi ara\u00e7lar, bu t\u00fcr uzun i\u00e7erikleri otomatik olarak birden fazla sayfaya b\u00f6lebilir ve \u00e7\u0131kt\u0131n\u0131n okunabilirli\u011fini koruyabilir.<\/p>\n<h3>PDF \u00c7\u0131kt\u0131s\u0131n\u0131 \u00d6zelle\u015ftirme ve Geli\u015ftirme Y\u00f6ntemleri<\/h3>\n<p>Olu\u015fturulan PDF&#8217;lerin sadece tweet i\u00e7eri\u011fini i\u00e7ermesi yeterli olmayabilir. Hukuki veya akademik kullan\u0131mlar i\u00e7in PDF&#8217;e ek bilgiler eklemek gerekebilir. \u00d6rne\u011fin:<\/p>\n<ul>\n<li><strong>\u00dcstbilgi ve Altbilgi (Headers &#038; Footers):<\/strong> Her sayfaya otomatik olarak sayfa numaras\u0131, belge ad\u0131 veya ar\u015fivleme tarihi gibi bilgiler eklenebilir. Puppeteer, <code>displayHeaderFooter: true<\/code> se\u00e7ene\u011fi ile bu t\u00fcr i\u00e7erikleri kolayca eklemenizi sa\u011flar.<\/li>\n<li><strong>Metin Arama Yetene\u011fi:<\/strong> E\u011fer tweet metni resim olarak de\u011fil, metin olarak PDF&#8217;e g\u00f6m\u00fcl\u00fcyorsa, PDF&#8217;in i\u00e7inde metin arama yap\u0131labilir. Bu, \u00f6zellikle b\u00fcy\u00fck ar\u015fivlerde \u00e7ok \u00f6nemlidir.<\/li>\n<li><strong>K\u00f6pr\u00fcler (Hyperlinks):<\/strong> Tweet&#8217;teki orijinal URL&#8217;lerin veya kullan\u0131c\u0131 ad\u0131 etiketlerinin (<code>@kullaniciadi<\/code>) PDF&#8217;te t\u0131klanabilir k\u00f6pr\u00fcler olarak kalmas\u0131n\u0131 sa\u011flamak, belgenin interaktifli\u011fini art\u0131r\u0131r.<\/li>\n<li><strong>Stil ve Tema:<\/strong> PDF&#8217;in g\u00f6rsel temas\u0131n\u0131 (\u00f6rne\u011fin, koyu mod veya \u00f6zel bir marka rengi) \u00f6zelle\u015ftirmek i\u00e7in HTML \u015fablonuna \u00f6zel CSS stilleri uygulanabilir. Bu, \u00e7\u0131kt\u0131n\u0131n daha profesyonel g\u00f6r\u00fcnmesini sa\u011flar.<\/li>\n<\/ul>\n<p>Bu optimizasyonlar, basit bir tweet \u00e7\u0131kt\u0131s\u0131n\u0131, i\u015flevsel ve profesyonel bir dijital belgeye d\u00f6n\u00fc\u015ft\u00fcrmenin anahtar\u0131d\u0131r. Her bir ipucu, uygulaman\u0131z\u0131n kalitesini art\u0131r\u0131rken, kullan\u0131c\u0131 deneyimini de zenginle\u015ftirecektir.<\/p>\n<h2>Sonu\u00e7 ve S\u0131k\u00e7a Sorulan Sorular<\/h2>\n<h3>Sonu\u00e7: Karma\u015f\u0131kl\u0131klarla Ba\u015fa \u00c7\u0131kmak M\u00fcmk\u00fcn m\u00fc?<\/h3>\n<p>Bir tweet&#8217;i PDF olarak kaydetme s\u00fcreci, g\u00f6r\u00fcn\u00fc\u015fte basit bir i\u015flem olsa da, asl\u0131nda web geli\u015ftirme d\u00fcnyas\u0131n\u0131n temel zorluklar\u0131n\u0131 bir araya getiren karma\u015f\u0131k bir g\u00f6revdir. CORS k\u0131s\u0131tlamalar\u0131, API kimlik do\u011frulama mekanizmalar\u0131 ve k\u00fcresel Unicode karakter setlerinin do\u011fru i\u015flenmesi gibi engeller, bu s\u00fcreci beklentilerin \u00f6tesinde zorla\u015ft\u0131r\u0131r. Ancak bu makalede detaylar\u0131yla inceledi\u011fimiz gibi, bu karma\u015f\u0131kl\u0131klar\u0131n \u00fcstesinden gelmek i\u00e7in etkili teknik \u00e7\u00f6z\u00fcmler mevcuttur. Twitter API&#8217;si ile yap\u0131land\u0131r\u0131lm\u0131\u015f veri \u00e7ekimi, Puppeteer gibi headless taray\u0131c\u0131lar arac\u0131l\u0131\u011f\u0131yla sunucu taraf\u0131nda PDF olu\u015fturma ve CORS sorunlar\u0131n\u0131 a\u015fmak i\u00e7in proxy sunucular\u0131 kullanma gibi stratejiler, g\u00fcvenilir ve y\u00fcksek kaliteli bir \u00e7\u0131kt\u0131 elde etmenin anahtar\u0131d\u0131r. Do\u011fru ara\u00e7lar\u0131 ve yakla\u015f\u0131mlar\u0131 bir araya getirerek, tweet&#8217;lerin dijital ar\u015fivlemesini sa\u011flam ve eksiksiz bir \u015fekilde ger\u00e7ekle\u015ftirmek m\u00fcmk\u00fcnd\u00fcr. Bu s\u00fcre\u00e7, sadece teknik bir ba\u015far\u0131 de\u011fil, ayn\u0131 zamanda dijital i\u00e7eriklerin korunmas\u0131 ve do\u011frulanmas\u0131 a\u00e7\u0131s\u0131ndan da \u00f6nemli bir ad\u0131md\u0131r.<\/p>\n<h3>S\u0131k\u00e7a Sorulan Sorular (SSS)<\/h3>\n<ul>\n<li>\n        <strong>Neden sadece ekran g\u00f6r\u00fcnt\u00fcs\u00fc almak yeterli de\u011fil?<\/strong><\/p>\n<p>Ekran g\u00f6r\u00fcnt\u00fcleri, metin olarak aranamaz, meta verileri (tarih, yazar) eksik olabilir ve kolayca manip\u00fcle edilebilir. Yasal veya akademik ba\u011flamlarda do\u011frulanabilirli\u011fi d\u00fc\u015f\u00fckt\u00fcr. PDF ise metin arama, meta veri ekleme ve daha profesyonel bir sunum imkan\u0131 sunar.<\/p>\n<\/li>\n<li>\n        <strong>Bir tweet&#8217;i PDF olarak kaydetmek yasal m\u0131?<\/strong><\/p>\n<p>Genel olarak, ki\u015fisel ar\u015fivleme veya adil kullan\u0131m (fair use) kapsam\u0131nda tweet&#8217;leri kaydetmek yasal olabilir. Ancak, ticari ama\u00e7larla veya ba\u015fkalar\u0131n\u0131n haklar\u0131n\u0131 ihlal edecek \u015fekilde kullanmak yasa d\u0131\u015f\u0131 olabilir. Her zaman Twitter&#8217;\u0131n kullan\u0131m ko\u015fullar\u0131n\u0131 ve yerel telif hakk\u0131 yasalar\u0131n\u0131 g\u00f6zden ge\u00e7irmek \u00f6nemlidir.<\/p>\n<\/li>\n<li>\n        <strong>T\u00fcm bir tweet dizisini (thread) PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrebilir miyim?<\/strong><\/p>\n<p>Evet, bu m\u00fcmk\u00fcnd\u00fcr. Twitter API&#8217;sini kullanarak dizideki t\u00fcm tweet&#8217;leri \u00e7ekmeniz ve ard\u0131ndan bu tweet&#8217;leri do\u011fru s\u0131rayla bir HTML \u015fablonunda birle\u015ftirip sunucu taraf\u0131nda bir PDF olu\u015fturucu (\u00f6rne\u011fin Puppeteer) ile d\u00f6n\u00fc\u015ft\u00fcrmeniz gerekir.<\/p>\n<\/li>\n<li>\n        <strong>Geli\u015ftirici olmayanlar i\u00e7in en kolay yol nedir?<\/strong><\/p>\n<p>Geli\u015ftirici olmayanlar i\u00e7in en kolay yol, bu i\u015fi yapan online ara\u00e7lar\u0131 veya taray\u0131c\u0131 eklentilerini kullanmakt\u0131r. Ancak bu ara\u00e7lar\u0131n genellikle s\u0131n\u0131rlamalar\u0131 (CORS, Unicode deste\u011fi, reklamlar) olabilir ve tam kontrol sa\u011flamazlar. En basit y\u00f6ntem, taray\u0131c\u0131n\u0131z\u0131n &#8220;Yazd\u0131r&#8221; (Print) i\u015flevini kullanarak hedef olarak &#8220;PDF olarak kaydet&#8221; se\u00e7ene\u011fini se\u00e7mektir, ancak bu da g\u00f6rsel tutarl\u0131l\u0131kta sorunlar yaratabilir.<\/p>\n<\/li>\n<li>\n        <strong>Bu i\u015fi yapan haz\u0131r ara\u00e7lar var m\u0131?<\/strong><\/p>\n<p>Evet, baz\u0131 \u00fc\u00e7\u00fcnc\u00fc taraf web siteleri ve taray\u0131c\u0131 eklentileri tweet&#8217;leri PDF&#8217;e d\u00f6n\u00fc\u015ft\u00fcrme hizmeti sunmaktad\u0131r. Ancak bu ara\u00e7lar\u0131n g\u00fcvenilirli\u011fi, gizlilik politikalar\u0131 ve kapsaml\u0131 Unicode deste\u011fi gibi konularda dikkatli olunmal\u0131d\u0131r. \u00c7o\u011fu zaman en iyi ve en kontrol edilebilir \u00e7\u00f6z\u00fcm, yukar\u0131da a\u00e7\u0131klanan tekniklerle kendi arac\u0131n\u0131z\u0131 geli\u015ftirmektir.<\/p>\n<\/li>\n<\/ul>\n<p>#WebGeli\u015ftirme #PDFOlu\u015fturma #CORS #API #Unicode #Teknoloji #TwitterAPI<\/p>\n<div class=\"github-example-link\"><strong>\u00d6rnek kod:<\/strong> <a href=\"https:\/\/github.com\/fatihsoysalcom\/tweet-data-fetch-unicode-demo\" target=\"_blank\" rel=\"noopener noreferrer\">github.com\/fatihsoysalcom\/tweet-data-fetch-unicode-demo<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"Bir tweet&#8217;i PDF olarak ar\u015fivlemek, ilk bak\u0131\u015fta sadece bir &#8220;kaydet&#8221; d\u00fc\u011fmesine basmak kadar kolay g\u00f6r\u00fcnebilir.","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-43877","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Tweet&#039;i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tweet&#039;i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri\" \/>\n<meta property=\"og:description\" content=\"Bir tweet&#039;i PDF olarak ar\u015fivlemek, ilk bak\u0131\u015fta sadece bir &quot;kaydet&quot; d\u00fc\u011fmesine basmak kadar kolay g\u00f6r\u00fcnebilir.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-06T06:15:17+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-06T06:15:57+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"27 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Tweet&#8217;i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri\",\"datePublished\":\"2026-08-06T06:15:17+00:00\",\"dateModified\":\"2026-08-06T06:15:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/\"},\"wordCount\":4480,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/\",\"name\":\"Tweet'i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-08-06T06:15:17+00:00\",\"dateModified\":\"2026-08-06T06:15:57+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tweet&#8217;i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Tweet'i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/","og_locale":"tr_TR","og_type":"article","og_title":"Tweet'i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri","og_description":"Bir tweet'i PDF olarak ar\u015fivlemek, ilk bak\u0131\u015fta sadece bir \"kaydet\" d\u00fc\u011fmesine basmak kadar kolay g\u00f6r\u00fcnebilir.","og_url":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-08-06T06:15:17+00:00","article_modified_time":"2026-08-06T06:15:57+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"27 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Tweet&#8217;i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri","datePublished":"2026-08-06T06:15:17+00:00","dateModified":"2026-08-06T06:15:57+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/"},"wordCount":4480,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/","url":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/","name":"Tweet'i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-08-06T06:15:17+00:00","dateModified":"2026-08-06T06:15:57+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/tweeti-pdf-olarak-kaydetmek-neden-bu-kadar-zor-cors-tokenlar-ve-unicode-engelleri\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Tweet&#8217;i PDF Olarak Kaydetmek Neden Bu Kadar Zor: CORS, Tokenlar ve Unicode Engelleri"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/43877","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=43877"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/43877\/revisions"}],"predecessor-version":[{"id":43878,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/43877\/revisions\/43878"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=43877"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=43877"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=43877"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}