Ferramenta web que recebe um username público do Instagram e exibe os 20 Reels mais recentes com métricas, análise por IA e visualizações de tendência.
Desafio técnico — VIEWX.COM.BR — Desenvolvedor Full-Stack
docker compose upAbra http://localhost:8000 no browser. Nada mais.
- Digite um
@usernamepúblico - O scraper busca o perfil + 20 Reels mais recentes direto da API do Instagram
- Exibe: métricas por Reel (views, likes, comentários, engagement rate), KPIs agregados, gráfico de tendência, tabela com sorting e export CSV
- Bônus: legenda de cada Reel, detecção de cross-post Facebook, análise por IA (OpenAI)
Backend: Python (FastAPI) + curl_cffi para scraping
Frontend: HTML/CSS/JS vanilla
Infra: 1 container Docker, docker compose up e pronto
FastAPI e asyncio são naturais pra I/O-bound (scraping). O ecossistema Python tem as melhores ferramentas pra HTTP/scraping.
O desafio pede uma ferramenta funcional, não um SPA com framework. Vanilla JS elimina build step, bundle, node_modules. O docker compose up sobe direto sem npm install. Priorizei funcionalidade e usabilidade sobre complexidade de toolchain.
Essa foi a decisão técnica mais importante do projeto.
O Instagram bloqueia requests baseado no TLS fingerprint da conexão. Bibliotecas Python (httpx, requests, aiohttp) têm fingerprint TLS diferente de um browser real — o Instagram detecta isso e retorna 429 (rate limit) independente do IP, proxy, ou cookies.
Testamos várias abordagens antes de chegar nessa solução:
| Abordagem | Resultado |
|---|---|
httpx sem auth |
429 — bloqueado por TLS fingerprint |
httpx + proxy residencial (iProyal) |
429 — proxy muda IP, mas fingerprint continua Python |
httpx + proxy + sessionid (login) |
Funciona, mas requer conta Instagram e cookie manual |
httpx + headers extras (Sec-Fetch-*, X-ASBD-ID) |
429 — headers não mudam fingerprint TLS |
| Scraping HTML da página de perfil | Dados insuficientes (Instagram carrega via JS) |
| GraphQL endpoint com doc_ids | 400/execution error sem auth |
curl_cffi com impersonate="chrome" |
200 — funciona sem proxy, sem login, sem nada |
curl-impersonate é um fork do curl que replica exatamente o handshake TLS do Chrome (cipher suites, extensões, ALPN, ordem dos headers). O curl_cffi é o binding Python. Com isso, o Instagram vê a request como vinda de um Chrome real.
Trade-off: curl_cffi é sync (não async). Resolvemos rodando o scraper em run_in_executor() pra não bloquear o event loop do FastAPI.
- URL (
instagram.com/reel/{code}) - Data de publicação (
taken_at) - Views (
play_count) - Likes (
like_count) - Comentários (
comment_count) - Engagement rate (calculado:
(likes + comments) / views * 100) - Legenda (
caption.text) — bônus - Duração (
video_duration) - Cross-post Facebook (
clips_metadata.is_shared_to_fb+has_shared_to_fb) — super bônus - Parceria paga (
is_paid_partnership) - Música (título + artista)
- Thumbnail e video URLs
- Coautores (
coauthor_producers)
O Instagram expõe dois campos na API de Reels:
clips_metadata.is_shared_to_fb— flag booleana no metadata do cliphas_shared_to_fb— flag numérica no objeto media (0 ou 1)
Se qualquer um dos dois for truthy, marcamos cross_post_fb: true. Não é heurística — são campos reais da API.
- Views médio: média de
play_countdos 20 Reels - Engagement rate médio: média dos ERs individuais
- Frequência de posts: intervalo médio em dias entre publicações
- Cross-posts FB: contagem de Reels compartilhados no Facebook
- Top hashtags: hashtags mais usadas nas legendas (top 10)
| Método | Rota | Body | Retorno |
|---|---|---|---|
| POST | /api/scrape |
{ "username": "..." } |
{ profile, reels, metrics } |
| POST | /api/analyze |
{ profile, reels, metrics, api_key } |
{ nicho, engajamento, audiencia, parcerias, pontos_fortes, pontos_fracos, recomendacao, tags, nota_geral } |
| GET | /api/proxy/image?url=... |
— | imagem (proxy) |
| GET | /* |
— | arquivos estáticos |
instagram-scraper/
docker-compose.yml
Dockerfile
requirements.txt
main.py — FastAPI app, rotas, serve estáticos
scraper.py — scraping Instagram (curl_cffi + impersonate Chrome)
analyzer.py — integração OpenAI (análise por IA com gpt-4o-mini)
frontend/
index.html
css/style.css
js/app.js
Priorizei o backend/scraper. O scraping do Instagram é a parte mais difícil e frágil do desafio — a API muda, bloqueia, exige workarounds. Um frontend bonito com dados mockados não demonstra competência técnica. Um scraper que funciona de verdade e entrega dados reais sim.
O frontend é funcional e usável — interface completa com perfil, KPIs, grid de Reels com thumbnails 9:16, modal com video player e métricas detalhadas, gráfico de tendência de views (CSS puro), tabela com sorting por coluna, export CSV, e seção de relatório IA. Tudo responsivo (mobile 2 colunas, tablet 3, desktop 4).
Usei Claude Code com Opus 4.6 como par de programação durante todo o desenvolvimento.
- Estrutura inicial do projeto (Dockerfile, docker-compose, FastAPI boilerplate)
- Parsing dos campos da API do Instagram (
_parse_reel,calculate_metrics) - Template do frontend HTML/CSS/JS
- A decisão de usar
curl_cffi— depois de ver o 429, eu sugeri testar curl-impersonate baseado no conhecimento de que Instagram faz TLS fingerprinting. A IA testou e confirmou - Abordagem de proxy (iProyal) — eu sugeri integrar proxy residencial como primeira tentativa. Quando não resolveu sozinho, a investigação revelou que o problema era TLS, não IP
- Estrutura dos endpoints e campos — defini quais dados extrair e como organizar a resposta baseado no briefing do desafio
- Trade-offs de arquitetura — decisão de usar sync
curl_cfficomrun_in_executorem vez de reescrever tudo async
- Documentação do iProyal (via browser) pra formato de proxy
- GitHub do curl-impersonate pra entender o mecanismo de TLS fingerprinting
- Testes manuais com
curlpra validar que o problema era fingerprint e não autenticação
- Legenda de cada Reel (
caption.text) - Cross-post Facebook (campos
is_shared_to_fb+has_shared_to_fb) - Análise por IA (OpenAI gpt-4o-mini, prompt de social media manager sênior, relatório estruturado com nota, pontos fortes/fracos, recomendações)
- Detecção de nicho (via análise IA — hashtags, música, conteúdo)
- Gráfico de tendência (barras CSS puro, tooltips com views e data)
- Tabela com sorting (clique no cabeçalho para ordenar por qualquer coluna)
- Export CSV (download com todos os dados dos 20 Reels)
- Modal detalhado (video player + todas as métricas por Reel)
- Responsivo (mobile, tablet, desktop)