Burası senin web el kitabın. İster baştan sona bir kitap gibi oku, ister bir terimi unuttuğunda aşağıdaki fihristten bul, sadece o bölüme bak. Her bölümde önce terim düz Türkçeyle anlatılır, sonra canlı bir örnekle gösterilir — örnekler süs değil, gerçekten çalışıyor: butonlara bas, kutulara yaz, kurcala.
Bir de özel bir düğmen var: sağ üstteki 🔍 İncele. Onu açtıktan sonra örneklerin içinde neye tıklarsan, sana onun ne olduğunu ve ne işe yaradığını söylerim. Yani "bu şey neydi?" diye düşündüğün an → İncele'yi aç → üstüne tıkla.
Bir web sayfasını binaya benzetirsek HTML, binanın iskeletidir. Sayfada ne olduğunu söyler: "Burada bir başlık var, altında bir yazı, yanında bir resim, en altta bir buton." Hepsi bu. Rengi, güzelliği söylemez (o CSS'in işi), tıklanınca ne olacağını da söylemez (o JavaScript'in işi). Sadece ne var, ne yok — onu söyler.
HTML'in yapı taşına element denir. Bir elementi yazmak için adını köşeli parantezlerin içine yazarsın; buna tag (etiket) denir. Çoğu element bir açılış ve bir kapanış tag'inden oluşur, ikisinin arasına da içerik girer. Elemente ekstra bilgi vermek istersen açılış tag'inin içine attribute (özellik) yazarsın. Kulağa karışık geliyor ama tek satırda hepsi görünüyor:
<button id="kaydet">Kaydet</button> <button> → açılış tag'i: "burada bir buton başlıyor" id="kaydet" → attribute: butona ekstra bilgi (adı "kaydet" olsun) Kaydet → içerik: butonun üzerinde yazacak yazı </button> → kapanış tag'i: "buton burada bitti" (baştaki / işaretine dikkat)
Bu dört parçanın toplamına — açılışı, özellikleri, içeriği ve kapanışıyla — element denir. Bir HTML sayfası, iç içe geçmiş yüzlerce elementten oluşur; tıpkı iç içe kutular gibi. Bu kitabın bundan sonraki her "İskelet" bölümü, işine en çok yarayacak element türlerini tek tek tanıtıyor.
İşte web'in en çok kullanılan ama en az anlaşılan elementi: div. Sırrı şu: div, görünmez bir kutudur. Kendisi hiçbir şey göstermez; tek görevi başka elementleri bir arada tutmaktır. Neden gerekli? Çünkü "şu üç şeyi yan yana koy", "bu kartı sağa yasla", "şurayı komple gizle" diyebilmek için o şeylerin tek bir pakette olması gerekir. O paket div'dir.
span ise div'in minicik kardeşi: koca bir kutu değil, cümlenin içindeki birkaç kelimeyi paketlemek için kullanılır — mesela tek bir kelimeyi kırmızı yapmak istediğinde. Ezberi kolay: div = koli, span = etiket bandı.
Aşağıdaki örnekte gerçekten iç içe kutular var ama görünmüyorlar — çünkü div böyle bir şey. Butona bas, kenarlarını boyayayım, o zaman gör:
<div> ← dış koli (mavi) <div>İçimde bir <span>span</span> saklı</div> ← iç kutu (pembe) + span (sarı) <div>Ben ikinci div'im</div> </div>
Bir sayfadaki yazıların da türleri vardır ve her türün kendi elementi var. h1'den h6'ya kadar olanlar başlıktır: h1 en büyüğü ve en önemlisidir — sayfanın ana başlığı. Rakam büyüdükçe başlık küçülür. Önemli bir kural: her sayfada tek bir h1 olmalı, çünkü Google sayfanın ne anlattığını önce h1'den anlar (SEO dediğimiz şeyin ilk taşı).
Normal yazılar p (paragraf) elementine girer. Bir yazının içinde bir kısmı kalınlaştırmak istersen strong kullanılır. Başka bir sayfaya götüren tıklanabilir yazılar ise a elementidir (İngilizce "anchor", çapa) — nereye gideceğini href attribute'u söyler. Hepsi bir arada, canlı:
Bu bir p paragrafı. İçinde strong ile kalınlaştırılmış bir kısım ve a elementiyle yapılmış bir link var. Linke tıklarsan Bölüm 1'e gider, çünkü href öyle diyor.
<h1>Ana başlık</h1> <p>Yazı, <strong>kalın kısım</strong> ve <a href="https://garamsi.com">bir link</a>.</p>
Alt alta maddeler göstereceksen liste elementleri kullanılır ve mantığı çok basittir: listenin kendisi için bir kap, her madde için bir satır. Kap iki çeşit: ul maddelerin önüne nokta koyar (sırasız liste), ol ise 1, 2, 3 diye numaralar (sıralı liste). Her iki kabın içindeki her bir madde de li'dir (list item = liste elemanı).
<ul> <ol> <li>süt</li> <li>ürünü kazı</li> <li>domates</li> <li>fiyatı eşleştir</li> </ul> </ol>
Elindeki bilgi satır ve sütunlardan oluşuyorsa — fiyat listesi, puan cetveli, stok dökümü — tablo kullanılır. Adları İngilizce kısaltmalardan gelir ve bir kez çözünce bir daha unutmazsın: table tablonun kendisi. tr = table row, yani bir satır. td = table data, yani satırın içindeki bir hücre. th = table header, yani kalın görünen başlık hücresi.
Yani kurulum hep aynıdır: table'ın içine satır satır tr, her tr'nin içine hücre hücre td dizersin. "Tabloya satır ekle" demek = "yeni bir tr ekle" demek. Butonla dene — JavaScript gerçekten yeni bir tr ekleyecek:
| Ürün | Fiyat |
|---|---|
| Deri Cüzdan | $45 |
| Masa Matı | $89 |
<table> <tr> <th>Ürün</th> <th>Fiyat</th> </tr> ← başlık satırı <tr> <td>Cüzdan</td> <td>$45</td> </tr> ← veri satırı </table>
Kullanıcıdan bilgi almak istediğin her yer bir formdur: giriş ekranı, arama kutusu, sipariş sayfası. Parçaları şunlar ve her birinin görevi nettir:
form, parçaların hepsini saran kaptır — "bunlar birlikte gönderilecek" demektir. input tek satırlık giriş kutusudur ve type attribute'uyla kılıktan kılığa girer: type="text" yazı kutusu, type="number" sayı kutusu, type="checkbox" işaret kutusu, type="password" yıldızlı şifre kutusu, type="date" tarih seçici. textarea çok satırlı büyük yazı alanıdır (yorum, not). select açılır menüdür, seçenekleri option'dur. label kutunun yanındaki açıklama yazısıdır ve güzel bir huyu vardır: label'a tıklamak, bağlı olduğu kutuyu seçer — telefonda küçücük kutuyu tutturmaya çalışmaktan kurtarır. button da düğmedir; formun içindeyse formu gönderir.
Aşağıdaki form gerçekten çalışıyor — doldur, gönder. Ama dikkat: bilgiler hiçbir sunucuya gitmiyor, JavaScript yakalayıp sana geri gösteriyor:
<form> <label for="ad">Adın:</label> <input type="text" id="ad"> <select><option>Cüzdan</option></select> <textarea></textarea> <button type="submit">Gönder</button> </form>
Sayfaya görsel ve ses koymanın elementleri bunlar. En önemlisi img (image = resim). İki attribute'u ezbere bil: src (source = kaynak) resim dosyasının nerede olduğunu söyler — bir dosya adı ya da internet adresi olabilir. alt (alternative = yedek) ise resim yüklenemezse yerine gösterilecek yedek yazıdır; ayrıca görme engellilerin ekran okuyucusu bu yazıyı sesli okur ve Google resmin ne olduğunu buradan anlar. Yani alt hem nezaket hem SEO'dur.
Aşağıda ikisini de canlı görüyorsun: soldaki resmin src'si doğru, sağdakinin src'sini bilerek bozdum — bak, yerine alt yazısı çıktı:
src doğru → resim geldi
src bozuk → alt devrede
video ve audio da aynı mantık: src ile dosyayı gösterirsin. Tek fark, controls attribute'unu eklersen oynat/durdur düğmeleri gelir. Aşağıdakiler gerçek dosyalar — oynat:
video elementi (controls açık)
audio elementi — 1,5 saniyelik "bip"
<img src="logo.png" alt="Mağazanın logosu" width="96"> <video src="tanitim.mp4" controls></video> <audio src="zil.mp3" controls></audio>
CSS'e geçmeden önce şunu çözmemiz lazım: sayfada yüzlerce element varken, "şunu kırmızı yap" derken hangisini kastettiğimizi nasıl anlatacağız? Cevap: elementlere isim takarak. Bunun iki yolu var ve aralarındaki fark çok önemli:
id, bir elementin kimlik numarasıdır — TC kimlik gibi. Sayfada aynı id'den yalnızca bir tane olabilir. "id'si kaptan olan kutu" dediğinde tek bir kutudan bahsediyorsundur. class ise bir takım formasıdır — aynı formayı istediğin kadar elemente giydirebilirsin. "class'ı takim olan herkes" dediğinde, o formayı giyen kaç element varsa hepsinden bahsediyorsundur.
Aşağıda dört kutu var. Dördü de "takim" formasını giyiyor; ama üçüncüsünün ayrıca bir kimliği var: id="kaptan". Butonlarla farkı canlı gör:
HTML: <div class="takim" id="kaptan">...</div>
CSS'te seçerken: .takim { ... } ← baştaki NOKTA class demek
#kaptan { ... } ← baştaki KARE (#) id demek
JS'te seçerken: document.querySelectorAll('.takim') ← hepsi
document.getElementById('kaptan') ← tekHTML iskeletse, CSS her şeyin nasıl görüneceğidir: renkler, yazı tipleri, boşluklar, kenarlar, gölgeler, hizalamalar. CSS'in cümle yapısı hep aynıdır: önce kimi boyayacağını söylersin (az önce öğrendiğin class/id ile), sonra süslü parantez içinde özellik: değer çiftleri sıralarsın. Örneğin .kart { background: white; } demek, "kart formasını giyen herkesin arka planı beyaz olsun" demektir.
CSS'in gücünü görmenin en iyi yolu, aynı HTML'i farklı makyajlarla görmek. Aşağıdaki kart hep aynı kart — içeriği hiç değişmiyor. Sadece CSS değişiyor:
/* makyajsız — tarayıcının çıplak hali */
"Şık CSS"e basınca altta beliren üç özelliğin adını bil, yeter: border-radius köşeleri yuvarlatır, box-shadow gölge verir, gradient iki rengi birbirine akıtır. Modern görünümün dörtte üçü bu üçlüdür.
Aynı sayfa kocaman bilgisayar ekranında da, daracık telefon ekranında da düzgün görünmek zorunda. Buna responsive tasarım denir: ekran daralınca yan yana duran kutuların alt alta geçmesi, yazıların küçülmesi, menünün hamburger simgesine dönüşmesi… Sayfa, ekrana "cevap verir" (respond).
Bunu kendi gözünle görmenin en kolay yolu aşağıda. Kaydırıcı, sanki telefon ekranıymış gibi alanı daraltıyor — üç kartın kendini nasıl yeniden dizdiğine bak:
Perde arkasında iki CSS aracı çalışır: flexbox ("bu kutuları esnek diz, sığmazsa alta at") ve media query ("ekran 680 pikselden darsa şu kuralları uygula"). Adlarını bilmen yeter — gerisini kod yazan halleder. Bu okuduğun site de responsive: telefonda açarsan aynı içerik bambaşka dizilir.
İskelet (HTML) ve makyaj (CSS) tamam; ama sayfa hâlâ hareketsiz. Butona basınca bir şeyin OLMASI için JavaScript (kısaca JS) gerekir. JS, tarayıcının içinde çalışan gerçek bir programlama dilidir: tıklamayı duyar, hesap yapar, sayfayı anında değiştirir. Bu kitaptaki bütün canlı örnekler JS ile çalışıyor.
İki küçük ama gerçek örnek: sayaç, her basışında bir sayı artırıyor; saat ise her saniye kendini yeniliyor. İkisi de şu an senin telefonunda/bilgisayarında çalışıyor — sunucuda değil:
Canlı saat: --:--:--
let sayi = 0; // bir hafıza kutusu aç, 0 koy
function sayacArtir() { // "sayacArtir" adında bir komut tanımla
sayi = sayi + 1; // kutudaki sayıyı 1 artır
document.getElementById('sayac') // sayfada id'si "sayac" olan yeri bul
.textContent = sayi; // içine yeni sayıyı yaz
}
// butonun HTML'i: <button onclick="sayacArtir()">
// yani: "tıklanınca sayacArtir komutunu çalıştır"Şimdi işin mutfağından bir sır: senin yazdığın HTML aslında ölü bir metin dosyasıdır. Tarayıcı onu okuyunca kafasında canlı bir ağaç kurar — her element bir dal, iç içe elementler dalın dalları. İşte bu ağacın adı DOM (Document Object Model). JavaScript sayfayı değiştirirken aslında HTML dosyasına dokunmaz; bu canlı ağaca dal ekler, dal koparır, dalları boyar.
Aşağıda solda ağacın şeması, sağda o ağacın sayfadaki görünümü var. Butona bas: JS, DOM'a gerçekten yeni bir dal (li elementi) ekleyecek ve iki taraf birden değişecek:
Sepete ürün eklenince sayfanın yenilenmeden güncellenmesi, yazarken arama sonuçlarının belirmesi — hepsi JS'in DOM'u değiştirmesidir. Sağ üstteki 🔍 İncele modu da DOM ağacını okuyarak çalışıyor: tıkladığın dalın adına bakıp sana söylüyor.
Buradan itibaren konu görünüşten çıkıp veriye giriyor. İki programın birbirine bilgi yollaması gerektiğinde — senin Migros kazıyıcın fiyatları çekerken, n8n Telegram'a mesaj atarken — bilgiyi ortak bir zarfa koyarlar. O zarfın adı JSON. Kuralı tek cümle: her bilgi bir "anahtar": değer çiftidir. "ad" anahtarının değeri "Mustafa", "yas" anahtarının değeri 30… hepsi süslü parantez içinde.
En iyi öğrenme yolu: kendin yazıp zarfın oluşmasını izlemek. Aşağıya yaz, JSON sağda canlı kurulsun:
Renklere dikkat et, çünkü kurallar orada saklı: anahtarlar hep tırnaklı, "yazı değerleri" tırnaklı, sayılar tırnaksız, doğru/yanlış değerleri de çıplak true / false olarak yazılır. Bu dört kuralı bilirsen dünyadaki her JSON'u okuyabilirsin.
İki programın konuşabilmesi için bir kapı gerekir; o kapının adı API. Sen (daha doğrusu senin programın) kapıya bir istek (request) bırakırsın, karşı taraf bir yanıt (response) döndürür — yanıt da genellikle az önce öğrendiğin JSON zarfıdır. REST ise bu konuşmanın görgü kurallarıdır. En çok iki fiili duyacaksın: GET = "bana şunu ver" (okuma), POST = "al bunu kaydet" (yazma).
Lafta kolay; canlısı daha iyi. Aşağıdaki buton, bu sunucudaki gerçek bir dosyaya (api-demo.json) gerçek bir GET isteği atar. Yanıtın gelişini, durum kodunu ve süresini izle:
const cevap = await fetch('api-demo.json'); // GET isteği at, cevabı bekle
const veri = await cevap.json(); // JSON zarfını aç
// Artık veri.urunler bir liste — sayfaya işleyebilirsin.
// Migros kazıyıcın da aynen bunu yapıyor, adres farklı sadece:
// fetch('migros.com.tr/rest/search/...')API'de soran hep sensin. Peki karşı tarafta bir şey OLDUĞUNDA senin haberin nasıl olacak — her saniye sorup duracak mısın? Hayır. Bunun için webhook var: karşı tarafa kendi adresini bırakırsın, "bir şey olursa buraya haber at" dersin. Olay olduğunda O SANA istek atar. Kapıcıya her sabah "kargom geldi mi?" diye sormak API'dir; kapıcının kargo gelince seni araması webhook'tur.
Kalıcı veri — siparişler, fiyat geçmişi, üye listesi — bir veritabanında durur. Veritabanı dediğin şey aslında disiplinli tablolardan ibarettir: satırlar kayıtlar, sütunlar alanlar. SQLite, bu işin cep boyu hali: kurulum istemez, koca veritabanı tek bir dosyada yaşar (tracker'larındaki data.db dosyaları birer SQLite'tır). Büyük projelerde ise PostgreSQL, MySQL gibi ağabeyler kullanılır — mantık aynıdır.
Veritabanıyla konuşmanın dili de SQL'dir ve neredeyse İngilizce cümle gibidir. Dört kelimeyi bilirsen günlük işin görülür: SELECT = seç/getir, FROM = şu tablodan, WHERE = şu şarta uyanları, ORDER BY = şuna göre sırala. Butonlarla üç gerçek sorgu dene, tabloya etkisini gör:
SELECT * FROM meyveler;
Peki veri saklamak için illa sunucu ve veritabanı mı gerekir? Küçük şeyler için hayır. Her tarayıcının, her site için ayrılmış küçük bir cebi vardır: localStorage. Oraya koyduğun şey, sayfa kapansa da, bilgisayar yeniden başlasa da durur. Ama iki sınırı aklında tut: sadece o cihazda ve o tarayıcıda durur (telefonundan göremezsin) ve küçük veriler içindir.
Dene: bir not yaz, kaydet, sonra sayfayı yenile. Not yerinde olacak — sunucuya tek bayt gitmeden:
localStorage.setItem('notum', 'deri sipariş et'); // cebe koy
localStorage.getItem('notum'); // cepten oku
localStorage.removeItem('notum'); // cepten atArtık parçaları birleştirebiliriz. Bir web uygulamasının iki yakası vardır. Frontend = vitrin: kullanıcının tarayıcısında çalışan her şey, yani HTML + CSS + JavaScript üçlüsü. Backend = mutfak: sunucuda çalışan, veriyi saklayan, hesabı yapan, kimseye görünmeyen program — senin projelerinde bu rolü Flask oynuyor. İki yaka birbiriyle API üzerinden, JSON zarflarıyla konuşur:
Şimdi büyük sırrı söyleyeyim: bu okuduğun sitenin backend'i yok. Veri saklamıyor, hesap yapmıyor; bütün marifeti frontend'de. Sunucu sadece dosyaları postalıyor. "Sunucu gerektirmeyen site" diye sana anlattığım şeyin canlı kanıtındasın.
Her gün onlarca kez baktığın adres çubuğunun da bir anatomisi var ve parçalarının adını bilmek, hata ararken çok işine yarar. Gerçek bir adresi parçalayalım:
https://sebzemeyve.herthing.duckdns.org/urun?ad=domates#fiyat
Bir de sunucunun cevap notları vardır — durum kodları. Dört tanesini bil, yeter: 200 = tamam, geldi. 301 = adres değişmiş, seni yönlendirdim. 404 = öyle bir sayfa yok. 500 = sunucu içinde bir şey patladı. ("404 Not Found" esprilerinin kaynağı bu.)
Kodu yazdın; peki insanlar ona nasıl ulaşıyor? Yayına alma işine deploy denir. Şu an bu sayfayı okurken, isteğin şu yolculuğu yaptı — bu şema süs değil, senin sunucunun GERÇEK düzeni:
Üç terimi açalım: DNS, isimleri numaraya çeviren rehberdir — insanlar isim ezberler, bilgisayarlar IP numarası ister. Port, aynı sunucudaki programları ayıran kapı numarasıdır; bir binada çok daire olması gibi, senin sunucunda da her uygulama kendi portunda oturur. Reverse proxy ise binanın kapıcısıdır: dışarıdan gelen herkesi tek kapıdan karşılar, doğru daireye yönlendirir ve HTTPS kilidini o yönetir.
PWA (Progressive Web App), normal bir web sitesinin telefona uygulama gibi kurulabilen halidir. App Store yok, Google Play yok, onay bekleme yok, "uygulamayı indirin" diye yalvarma yok. Sitene üç parça eklersin; ziyaretçi isterse siteni ana ekranına kurar. Kurulunca kendi ikonuyla açılır, tarayıcı çubuğu görünmez, tam ekran çalışır — kullanıcı için normal bir uygulamadan farksızdır.
Bir PWA'yı PWA yapan üç parça:
Site şifreli bağlantıda olmalı (adres çubuğundaki kilit). Tarayıcı, güvensiz siteye kurulum izni vermez. Bu site HTTPS'te — şart tamam.
Uygulamanın kimlik kartı: adı ne, ikonu hangi dosya, açılış rengi ne, tam ekran mı açılsın. Tek küçük JSON dosyası.
Sayfa ile internet arasına yerleşen görevli: dosyaları cihaza önbellekler. İnternet gidince siteyi önbellekten açar — çevrimdışı çalışmanın sırrı budur.
Canlı durum — bu sayfanın PWA organları şu an ne halde:
Nasıl kurulur?
Kurduktan sonra asıl numarayı dene: telefonu uçak moduna al ve uygulamayı aç. Site yine açılacak — çünkü service worker her şeyi cihazına önbelleklemişti. İnternetsiz çalışan web sitesi; işte PWA'nın sihri bu.
Peki hangisini seçmeli? Üç yolun dürüst karşılaştırması:
| Mobil uyumlu site | PWA | Gerçek app (React Native) | |
|---|---|---|---|
| Kurulum | yok, tarayıcıdan | ana ekrana, mağazasız | App Store / Google Play |
| Çevrimdışı çalışma | ✗ | ✓ | ✓ |
| Bildirim gönderme | ✗ | ✓ (iPhone'da kısıtlı) | ✓ tam |
| Mağaza onayı/komisyonu | yok | yok | var (onay + %15-30) |
| Yapım maliyeti/emeği | en düşük | düşük (site + 3 parça) | yüksek (ayrı proje) |
| Ne zaman mantıklı? | çoğu iş için yeter | "app hissi" istenince | kamera/bluetooth gibi derin donanım gerekince |
Bu kitapta öğrendiğin her şey el emeğiyle yazılabilir; ama dünya, sık yapılan işler için hazır alet setleri üretmiş. Bunlara framework (çatı) ve kütüphane denir. Hepsi aynı üç temelin — HTML, CSS, JS — üstüne kuruludur. Prompt'ta adını doğru anarsan, LLM tam olarak ne istediğini anlar:
Python ile küçük web uygulaması yazmanın en pratik yolu. Tek dosyada site + API + veritabanı bağlantısı.
Sende: HCC Calculator ve tüm tracker'lar Flask.Flask'in API'ye odaklanmış modern kardeşi. Daha hızlı, dokümanı kendiliğinden oluşur.
Ne zaman: sayfa yok, sadece API yazılacaksa.Büyük ve karmaşık arayüzlerin en popüler JS kütüphanesi. Arayüzü yeniden kullanılabilir bileşenlere böler.
Dikkat: basit iş için ağırdır, önce basiti dene.React'in "her şey dahil" paketi: sayfa yönlendirme, SEO, sunucu tarafı — kutudan çıkar.
Yayınlanacak ciddi React sitesi = Next.js.Hazır mini CSS sınıflarıyla hızlı ve modern tasarım. LLM'lerle arası çok iyidir.
Prompt'a "Tailwind kullan" yaz, şık çıkar.Hazır bileşen seti (buton, menü, kart). Hızlıdır ama her Bootstrap sitesi birbirine benzer.
Eski usta; yeni işlerde Tailwind öne geçti.JS'i tarayıcı dışında (sunucuda) çalıştıran ortam + JS dünyasının paket mağazası.
Sende: n8n ve Telegram botun Node üstünde koşuyor.React'in iki rakibi: Vue öğrenmesi daha kolay, Svelte daha hafif ve hızlı.
LLM'ler React'te daha isabetli — varsayılan o olsun.Son bölüm, işin dedektiflik tarafı. Her tarayıcıda gizli bir mühendis paneli vardır: DevTools. Bilgisayarda F12'ye bas (ya da sayfaya sağ tıkla → "İncele"), açılır. İçinde üç sekme senin için altın değerinde: Elements DOM ağacını canlı gösterir, Network sayfanın attığı bütün API isteklerini listeler (kazıma işlerinde gizli API'leri burada buluyoruz), Console ise JS hatalarını gösterir. Bu kitaptaki 🔍 İncele modu, DevTools'un "element seç" okunun sana özel, Türkçe konuşan minik halidir.
CDP (Chrome DevTools Protocol) ise aynı panelin uzaktan kumandasıdır: bir program, tarayıcıya dışarıdan bağlanıp onu insan gibi kullanabilir — sayfa açar, tıklar, okur, ekran görüntüsü alır. Senin TripAdvisor kazıyıcın tam olarak böyle çalışıyor: Brave'e CDP kapısından (port 9223) bağlanıyor, otel puanlarını gerçek tarayıcının gözünden okuyor. DataDome gibi bot korumaları gerçek tarayıcı gördüğü için alarm çalmıyor.
İnsan → klavye + fare → Brave → tripadvisor.com Program → CDP (port 9223) → Brave → tripadvisor.com ← aynı tarayıcı, uzaktan kumandayla