Como Hackear Reservas de Roof Terraces em Londres com Python

A Tragédia dos Comuns Digital: O Desafio de Escalar Reservas em Espaços Públicos

Londres possui alguns dos mirantes mais espetaculares do mundo, e o melhor de tudo: muitos deles são totalmente gratuitos devido a acordos de planejamento urbano (conhecidos como acordos da Seção 106). No entanto, tentar reservar um horário no Horizon 22, Sky Garden ou The Lookout tornou-se uma tarefa quase impossível para humanos comuns. Os ingressos esgotam em segundos, não porque existem milhões de turistas clicando simultaneamente, mas devido à presença massiva de bots de agendamento e sistemas proprietários ineficientes que criam uma escassez artificial.

As informações originais sobre a infraestrutura física e a experiência de visitação desses espaços foram detalhadas no Artigo de Origem, que serve como base empírica para o nosso estudo de caso de engenharia reversa. Como desenvolvedores, quando nos deparamos com um sistema de reserva que falha sob carga ou que favorece scalpers, nossa resposta imediata é: podemos automatizar isso de forma mais eficiente e justa?

Neste guia técnico profundo, vamos analisar a arquitetura dos sistemas de reserva por trás dos principais terraços gratuitos de Londres, realizar a engenharia reversa de suas APIs ocultas, construir um bot de monitoramento resiliente em Python e discutir como transformar essa automação em um modelo de Micro-SaaS lucrativo.

Engenharia Reversa dos Portais de Reserva (Sky Garden, Horizon 22 e Lookout)


Asset por BlackDog1966 via Pixabay

Para automatizar qualquer sistema de reservas, primeiro precisamos entender como ele se comunica com o servidor. A maioria dessas plataformas não reconstrói a página inteira a cada clique; elas utilizam APIs REST assíncronas que retornam payloads em JSON contendo a disponibilidade de slots de tempo.

Análise de Tráfego e Descoberta de APIs Ocultas

Ao abrir o console de desenvolvedor do Google Chrome (F12) na aba Network (Rede) e filtrar por requisições do tipo Fetch/XHR enquanto navega pelo calendário do Horizon 22, podemos identificar o endpoint exato que retorna os dias disponíveis. Em vez de renderizar o calendário visualmente, o frontend faz uma requisição GET para um endpoint estruturado da seguinte forma:

GET /api/v1/slots?venue_id=102&start_date=2026-06-01&end_date=2026-06-30 HTTP/1.1
Host: booking.horizon22.co.uk
Authorization: Bearer [JWT_TOKEN]
Accept: application/json

O payload de resposta é um JSON limpo, que nos diz exatamente quais dias possuem vagas e quantos ingressos restam por horário:

{
  "success": true,
  "data": [
    {
      "date": "2026-06-15",
      "available_slots": [
        {"time": "09:15", "capacity_remaining": 4, "ticket_type_id": 901},
        {"time": "10:30", "capacity_remaining": 1, "ticket_type_id": 901}
      ]
    }
  ]
}

Contornando Proteções: Cloudflare, Captchas e TLS Fingerprinting

Plataformas de alta demanda frequentemente implementam firewalls de aplicação web (WAF) como Cloudflare ou Akamai para mitigar ataques de negação de serviço (DDoS) e bloquear scrapers. Se você tentar fazer uma requisição simples usando a biblioteca requests do Python, receberá imediatamente um erro 403 Forbidden devido ao bloqueio de User-Agent ou, pior, um desafio de JavaScript (Cloudflare Turnstile).

Para contornar essas proteções de forma ética e robusta, precisamos emular perfeitamente o comportamento de um navegador real. Isso envolve:

  • TLS Fingerprinting (JA3): Os WAFs modernos analisam o aperto de mão (handshake) TLS do seu cliente HTTP. Bibliotecas padrão como urllib ou requests possuem assinaturas TLS muito diferentes do Chrome ou Firefox. Usaremos a biblioteca curl_cffi ou tls_client em Python para forçar o handshake a se parecer exatamente com o de um navegador moderno.
  • Automação Headless com Evasão: Em vez de requisições HTTP puras, utilizaremos o Playwright em modo headless combinado com o pacote playwright-stealth para ocultar variáveis de ambiente que revelam a automação (como navigator.webdriver).

Arquitetura do Sistema: O Bot de Agendamento Open-Source (TerraceBot)

Para criar um sistema resiliente, não podemos confiar em um script síncrono simples que roda em loop infinito. Se o servidor cair ou a conexão oscilar, o bot falhará. Projetamos o TerraceBot utilizando uma arquitetura orientada a eventos, dividida em três microsserviços principais:

  1. Scraper/Monitor: Um worker leve que consulta continuamente os endpoints de disponibilidade usando proxies rotativos.
  2. Fila de Mensageria (Redis): Armazena os slots encontrados e gerencia o estado das tarefas de agendamento para evitar reservas duplicadas.
  3. Booking Engine (Playwright Worker): Quando um slot disponível é detectado, este worker é disparado para preencher o formulário de reserva, resolver captchas (usando serviços de API como 2Captcha ou CapSolver) e confirmar o agendamento.

Diagrama de Fluxo de Dados

[API de Disponibilidade] 
       │ (Polling via curl_cffi com Proxy Rotativo)
       ▼
[Monitor Worker] ──(Se houver vaga)──> [Fila Redis] ──> [Booking Worker (Playwright)]
                                                               │
                                                               ├──> [Confirmação de Reserva]
                                                               └──> [Notificação Telegram/Discord]

O Módulo de Scraping e Monitoramento em Tempo Real (Python)

Abaixo está a implementação do módulo de monitoramento utilizando curl_cffi para contornar o TLS Fingerprinting. Este script monitora a API de disponibilidade e envia um alerta assim que um slot livre é detectado.

import time
import json
from curl_cffi import requests

API_URL = "https://api.horizon22.co.uk/v1/slots?venue_id=102&start_date=2026-06-01&end_date=2026-06-30"
HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Accept": "application/json",
    "Accept-Language": "en-US,en;q=0.9",
    "Referer": "https://booking.horizon22.co.uk/",
    "Origin": "https://booking.horizon22.co.uk"
}

def check_availability():
    try:
        # Usando impersonate='chrome120' para emular o fingerprint TLS do Chrome
        response = requests.get(API_URL, headers=HEADERS, impersonate="chrome120", timeout=10)
        if response.status_code == 200:
            payload = response.json()
            for day in payload.get("data", []):
                date = day.get("date")
                slots = day.get("available_slots", [])
                if slots:
                    print(f"[ALERTA] Vagas encontradas para o dia {date}!")
                    for slot in slots:
                        print(f"  - Horário: {slot['time']} ({slot['capacity_remaining']} vagas restantes)")
                    trigger_booking_pipeline(date, slots)
        elif response.status_code == 403:
            print("[ERRO] Bloqueado pelo Cloudflare. Rotacionando proxy...")
        else:
            print(f"[ERRO] Status Code inesperado: {response.status_code}")
    except Exception as e:
        print(f"[ERRO] Falha na requisição: {str(e)}")

def trigger_booking_pipeline(date, slots):
    # Aqui conectamos com a fila Redis para disparar o worker do Playwright
    pass

if __name__ == "__main__":
    while True:
        print("[INFO] Verificando disponibilidade...")
        check_availability()
        time.sleep(30) # Intervalo de segurança para evitar rate limiting

O Módulo de Reserva Automatizada com Playwright

Uma vez detectada a vaga, o worker do Playwright entra em ação para simular a interação humana e finalizar o processo de checkout. O script abaixo demonstra como inicializar o navegador de forma furtiva e preencher os dados do usuário.

import asyncio
from playwright.async_api import async_playwright
from playwright_stealth import use_stealth_async

async def perform_booking(target_date, target_time, user_info):
    async with async_playwright() as p:
        # Lançando o navegador com argumentos para evitar detecção
        browser = await p.chromium.launch(headless=True, args=[
            "--disable-blink-features=AutomationControlled",
            "--no-sandbox"
        ])
        context = await browser.new_context(
            viewport={"width": 1920, "height": 1080},
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
        )
        page = await context.new_page()
        await use_stealth_async(page)

        # Navegando diretamente para a página de checkout do slot específico
        booking_url = f"https://booking.horizon22.co.uk/checkout?date={target_date}&time={target_time}"
        print(f"[WORKER] Acessando {booking_url}")
        await page.goto(booking_url, wait_until="networkidle")

        # Preenchendo o formulário de reserva
        await page.fill("input[name='first_name']", user_info['first_name'])
        await page.fill("input[name='last_name']", user_info['last_name'])
        await page.fill("input[name='email']", user_info['email'])
        await page.fill("input[name='phone']", user_info['phone'])
        
        # Aceitando os termos de serviço
        await page.click("input[type='checkbox']#terms-agreement")

        # Submetendo o formulário
        print("[WORKER] Submetendo reserva...")
        await page.click("button[type='submit']#confirm-booking")
        
        # Aguardando a tela de sucesso
        await page.wait_for_selector(".booking-success-confirmation", timeout=15000)
        print("[SUCESSO] Reserva concluída com êxito!")
        await page.screenshot(path=f"confirmation_{target_date}.png")
        
        await browser.close()

# Exemplo de execução do loop de eventos
# asyncio.run(perform_booking('2026-06-15', '10:30', {
#     'first_name': 'John', 'last_name': 'Doe', 
#     'email': 'john.doe@example.com', 'phone': '+447700900077'
# }))

Transformando Automação em Micro-SaaS: Monetização e Oportunidades de Mercado


Asset por ps_composition via Pixabay

Para desenvolvedores interessados em transformar scripts utilitários em fontes recorrentes de receita, a transição de um simples bot local para uma arquitetura multi-tenant é o caminho ideal. Explore mais sobre este ecossistema em nossa categoria de Automações e Micro-SaaS.

O mercado de turismo e conveniência em grandes metrópoles como Londres, Paris e Nova York é altamente lucrativo. Turistas de alto padrão e agências de viagens corporativas estão dispostos a pagar taxas de conveniência para garantir acesso a atrações exclusivas sem o estresse de monitorar calendários manualmente.

Modelos de Monetização para Bots de Conveniência

  • Notificação Premium (Freemium): O usuário se cadastra gratuitamente para receber alertas de vagas remanescentes no Telegram com 15 minutos de atraso. Assinantes premium (ex: £4.99/mês) recebem alertas instantâneos via SMS/WhatsApp com link direto de checkout pré-preenchido.
  • Concierge de Agendamento (SaaS Completo): O cliente insere seus dados, seleciona a faixa de datas desejada e o número de ingressos. O sistema cobra uma taxa fixa por reserva bem-sucedida (ex: £10 por ingresso garantido). O pagamento só é processado após a emissão do ticket oficial (modelo baseado em sucesso).
  • API B2B para Agências de Turismo: Disponibilização de endpoints para que agências de viagens integrem a reserva automatizada de mirantes gratuitos em seus pacotes de turismo personalizados de forma invisível para o cliente final.

Tabela Comparativa: Viabilidade de Automação por Atração

Abaixo, analisamos a viabilidade técnica e comercial de automatizar as principais atrações gratuitas de Londres com base na complexidade de suas APIs e na demanda do mercado.

Atração Dificuldade da API Proteção contra Bots Janela de Reserva Potencial de Monetização
Horizon 22 Média (REST JSON) Cloudflare Turnstile Diária / Semanal Altíssimo
Sky Garden Alta (GraphQL / Custom) Akamai + Queue-it Toda segunda-feira às 9h Alto
The Lookout Baixa (Eventbrite API) Padrão Eventbrite Mensal Médio
Garden at 120 Nenhuma (Sem reserva prévia) Nenhuma (Fila física) Acesso livre Nulo

Estratégias Avançadas de Infraestrutura e Deploy Resiliente

Para operar um Micro-SaaS de automação de forma profissional, você não pode rodar scripts em sua máquina local. É necessária uma infraestrutura distribuída, tolerante a falhas e que minimize o risco de banimento de IPs.

Gerenciamento de Proxies Residenciais Rotativos

Datacenters tradicionais (AWS, DigitalOcean, Hetzner) possuem blocos de IPs conhecidos e amplamente bloqueados por WAFs. Para garantir que suas requisições de monitoramento pareçam tráfego legítimo de usuários domésticos, você deve utilizar redes de Proxies Residenciais Rotativos (como Bright Data, Oxylabs ou Smartproxy).

Esses serviços fornecem um endpoint de proxy único que, a cada requisição HTTP, encaminha o tráfego através de um dispositivo residencial real (conexões Wi-Fi domésticas, 4G/5G) em Londres. Isso torna virtualmente impossível para o Cloudflare bloquear o bot com base apenas no IP, pois o bloqueio afetaria usuários reais.

Tratamento de Erros, Idempotência e Filas de Mensageria

Quando lidamos com automação de checkout, a idempotência é crucial. Você não quer que uma falha de rede temporária faça com que o bot envie o formulário de reserva duas vezes, resultando em cobranças duplicadas ou cancelamento de ingressos por violação de termos de uso.

Utilizando o Celery com Redis como broker, podemos definir políticas rígidas de retry com backoff exponencial:

@app.task(bind=True, max_retries=3, default_retry_delay=5)
def run_booking_task(self, user_data, slot_details):
    try:
        # Executa a reserva de forma síncrona dentro do worker
        result = execute_playwright_booking(user_data, slot_details)
        return result
    except TemporaryNetworkError as exc:
        # Retenta a tarefa em caso de erro de rede temporário
        raise self.retry(exc=exc, countdown=2 ** self.request.retries)
    except HardValidationError as exc:
        # Não retenta se os dados do usuário forem inválidos
        log_error_to_sentry(exc)
        raise exc

Considerações Éticas, Termos de Serviço e o Futuro do Acesso Público

Como engenheiros de software, temos a responsabilidade de avaliar o impacto social de nossas criações. A automação de reservas de espaços públicos gratuitos caminha em uma linha tênue entre a otimização tecnológica e a exclusão social. Se todos usarem bots, o acesso aos mirantes deixará de ser democrático e passará a ser restrito àqueles que possuem conhecimento técnico ou recursos financeiros para pagar por serviços de concierge.

No entanto, a existência dessas automações expõe a fragilidade e a obsolescência dos sistemas de TI contratados pelo poder público e por grandes corporações imobiliárias. Ao expor essas vulnerabilidades de forma transparente e propor soluções de código aberto, forçamos a indústria a adotar mecanismos de autenticação mais robustos, como verificação de identidade real vinculada ao passaporte ou documento nacional, sorteios justos (lottery systems) em vez de filas por ordem de chegada, e APIs públicas oficiais que distribuam os ingressos de forma equitativa.

O desenvolvimento de ferramentas open-source de monitoramento não deve visar o monopólio de ingressos para revenda ilegal (scalping), mas sim a democratização da informação, permitindo que qualquer cidadão receba notificações em tempo real quando um espaço público de sua cidade estiver disponível para visitação.

📚 Fontes E Referências

  1. London’s Free Roof TerracesPortal Internacional

Como Lucrar com Scrapers Quebrados no Micro-SaaS

O Pesadelo Silencioso do Custo de Manutenção em Bootstrapping


Foto por Storme22k via Pixabay

Como um Diretor Financeiro (CFO) focado em bootstrapping, eu olho para cada linha de código escrita não como um ativo, mas como um passivo financeiro futuro. No ecossistema de startups enxutas, o recurso mais escasso e caro não é o servidor da AWS; é o tempo de engenharia. Quando vi o relato de um desenvolvedor que passou semanas corrigindo scrapers quebrados em vez de trabalhar em seu produto principal, meu cérebro financeiro imediatamente calculou o prejuízo invisível desse cenário.

Web scraping é, por natureza, uma batalha constante contra o caos. Sites mudam suas estruturas de HTML, implementam novos sistemas de proteção contra bots e alteram seletores CSS sem aviso prévio. Para um fundador solo ou uma equipe ultra-reduzida, gastar 30% a 50% da semana de trabalho ajustando seletores XPath é uma rota expressa para a falência técnica e operacional. Você não está construindo valor; você está apenas pagando juros sobre uma dívida técnica que nunca contraiu voluntariamente.

A Anatomia do Desperdício: Quanto Custa um Scraper Quebrado?

Vamos colocar os números na mesa. Se você é um desenvolvedor sênior atuando como fundador técnico, seu custo de oportunidade estimado de mercado é de pelo menos $80 a $120 por hora. Se você gasta 10 horas por semana consertando scrapers que quebraram devido a atualizações de terceiros, estamos falando de um custo direto de aproximadamente $4.000 por mês em pura manutenção reativa.

Este é o clássico erro de alocação de capital humano. Em vez de investir esse tempo em canais de aquisição de clientes, melhorias de UX ou estratégias de retenção, você está gastando recursos preciosos para manter o status quo do seu produto. Para entender como otimizar a alocação de recursos e precificar soluções de forma inteligente, vale a pena explorar as dinâmicas de mercado detalhadas na nossa categoria de Negócios e Monetização.

O Pivot Estratégico: De Vítima a Provedor de Soluções

O ponto de virada ocorre quando o fundador percebe que a dor que ele sente é uma dor universal e altamente monetizável. Em vez de continuar aceitando o prejuízo, o desenvolvedor do nosso caso de estudo decidiu transformar o seu problema em um produto de software independente. Se a manutenção de scrapers é um inferno para ele, também o é para milhares de outras empresas que dependem de extração de dados da web.

As informações originais sobre essa transição dolorosa, mas extremamente lucrativa, foram detalhadas no Artigo de Origem. O insight fundamental aqui é simples: em uma corrida do ouro, não cave ouro; venda picaretas. Se o seu produto principal está sofrendo para obter tração porque você está ocupado demais mantendo a infraestrutura de dados, talvez a própria infraestrutura de dados seja o seu verdadeiro produto de alta margem.

Análise de Viabilidade: Construir vs. Comprar vs. Pivotar

Para ilustrar a diferença financeira entre as abordagens, estruturei uma tabela comparativa sob a ótica de eficiência de capital. Ela demonstra o impacto de longo prazo na saúde financeira de uma operação bootstrapped:

Métrica de Comparação Abordagem 1: Manutenção Interna Abordagem 2: Terceirização via API Externa Abordagem 3: Pivotar para Micro-SaaS Próprio
Custo Financeiro Direto (Mensal) Alto ($3.000 – $5.000 em tempo de dev) Médio ($100 – $500 em taxas de API) Baixo (Custo de infraestrutura básico)
Foco no Core Business Severamente comprometido Totalmente preservado Redefinido (O scraper vira o core)
Potencial de Geração de Receita Zero (Apenas centro de custo) Indireto (Através do produto principal) Direto (Venda de assinaturas recorrentes)
Escalabilidade Operacional Péssima (Mais dados = mais quebras) Excelente (Escala sob demanda) Exponencial (Infraestrutura vira produto)

Como Monetizar a Dor Alheia com um Micro-SaaS de Scraping


Foto por blickpixel via Pixabay

Se você decidiu seguir o caminho de empacotar sua solução de scraping para o mercado, a precificação e o posicionamento estratégico determinarão sua sobrevivência. Como CFO, eu desaconselho fortemente o modelo puramente gratuito ou freemium agressivo para esse tipo de serviço. O custo de largura de banda, proxies rotativos e poder computacional para renderização de JavaScript (via headless browsers como Puppeteer ou Playwright) pode escalar rapidamente, destruindo suas margens brutas.

Em vez disso, adote um modelo de precificação baseado em consumo com um piso de assinatura fixa (Hybrid Pricing). Isso garante que você cubra seus custos fixos de infraestrutura enquanto captura o valor excedente dos usuários de alto volume. Por exemplo, um plano básico de $29/mês que inclui 50.000 requisições bem-sucedidas, cobrando uma taxa marginal por bloco de 1.000 requisições adicionais.

A Importância da Margem Bruta em Projetos de Extração de Dados

Em negócios baseados em APIs de scraping, a margem bruta é a métrica rainha. Seus principais custos de vendas (COGS) serão os provedores de proxy (especialmente proxies residenciais, que são caros) e servidores de computação em nuvem. Para manter uma operação saudável de bootstrapping, sua margem bruta deve ser de, no mínimo, 70%.

Para alcançar isso, você precisa otimizar o código de extração para evitar requisições desnecessárias. Implementar cache agressivo para páginas que não mudam frequentemente e usar proxies de forma inteligente (apenas quando houver bloqueio detectado) são estratégias técnicas com impacto financeiro direto e imediato no seu balanço patrimonial.

Lições de Bootstrapping para Fundadores Técnicos

A maior lição que podemos tirar desse cenário é a necessidade de manter uma postura implacável em relação ao desperdício de tempo. Se você passa mais tempo defendendo seu software contra o ambiente externo do que adicionando valor para o cliente final, seu modelo de negócios está quebrado, mesmo que seu código seja perfeito.

Substitua o orgulho de engenharia pela eficiência financeira. Se uma ferramenta de terceiros pode resolver seu problema de extração por uma fração do seu custo de desenvolvimento, compre-a. Se você desenvolveu uma solução interna robusta o suficiente para resolver essa dor de forma definitiva, pare de tratá-la como um utilitário interno e comece a tratá-la como um gerador de receita recorrente.

Sair da versão mobile