GitDownloader
Blog

Como Baixar uma Pasta do GitHub Sem Clonar o Repositório Inteiro

Abra quase qualquer repositório no GitHub e você encontrará um botão verde Code que oferece exatamente duas coisas: clonar o projeto inteiro ou baixar um ZIP do projeto inteiro. Entre em src/components, docs/examples ou em uma pasta templates, e o botão continua lá — mas ele ainda entrega tudo. A própria documentação do GitHub é direta sobre isso: você pode baixar um snapshot dos arquivos de um repositório, cloná-lo ou fazer um fork. Não existe uma quarta opção para uma pasta.

É justamente essa lacuna que faz de “como baixar uma pasta do GitHub” uma das perguntas mais pesquisadas sobre o GitHub, e que explica por que as respostas que você encontra são tão inconsistentes. Algumas ainda recomendam um comando SVN que parou de funcionar em janeiro de 2024. Outras entregam uma receita Git de cinco comandos que, no fundo, baixa o repositório inteiro de qualquer jeito. Este guia cobre todos os métodos que realmente funcionam hoje, o que cada um custa e os erros específicos — limites de requisições, listagens de arquivos truncadas, arquivos de ponteiro do LFS — que definem qual deles é o certo para o seu caso.

Resposta rápida: escolha o seu método

Método Exige instalação Repositórios privados Mantém o histórico do Git Melhor para
Downloader de pasta no navegador Não Sim, com um token Não Downloads pontuais, pastas de tamanhos variados
ZIP do repositório (oficial) Não Sim, com um token Não Repositórios pequenos em que você precisa da maioria dos arquivos
git sparse-checkout Git Sim, com credenciais Sim Você vai continuar puxando atualizações
API REST + curl curl, jq Sim, com um token Não Scripts, CI, tarefas repetíveis
Copiar arquivos individuais Não Sim, via API Não Dois ou três arquivos de uma pasta

Se você só quer o ZIP, o caminho pelo navegador é o mais rápido — cole a URL da pasta na ferramenta da página inicial do GitDownloader e ela empacota apenas aquele diretório. O restante deste artigo explica por que as outras opções existem e quando elas são a escolha melhor.

Por que o GitHub não tem um botão de “baixar esta pasta”

A limitação não é preguiça; ela decorre de como o Git armazena dados.

Um repositório Git é um grafo direcionado de objetos. Os arquivos vivem em objetos blob, e os diretórios são objetos tree que listam nomes, modos e hashes apontando para blobs ou outras trees. Um branch é um ponteiro para um commit, que aponta para uma tree raiz, que descreve transitivamente todo o snapshot. Nada nessa estrutura representa “a pasta src/assets como uma unidade independente e baixável” — uma subárvore só tem significado dentro da sua tree pai.

O Subversion, em contrapartida, tratava diretórios como alvos de checkout de primeira classe, e é por isso que a antiga ponte SVN foi o contorno clássico. O modelo do Git te dá histórico, ramificação e integridade; o preço é que a recuperação parcial é um problema do lado do cliente, não um conceito do repositório.

A interface do GitHub, portanto, oferece o que é barato e inequívoco de servir:

  • Um ZIP de uma ref. https://github.com/{owner}/{repo}/archive/refs/heads/{branch}.zip transmite um snapshot da tree raiz daquele branch. Útil, mas sempre o branch inteiro.
  • A Git Trees API, que consegue listar uma subárvore em uma única requisição. Essa é a primitiva sobre a qual toda ferramenta de download de pasta é realmente construída — inclusive a nossa.

Então baixar uma pasta não é algo que o GitHub faz por você. É algo que uma ferramenta ou um script faz com a API do GitHub, listando os arquivos sob um caminho, buscando cada um e compactando o resultado localmente.

Método 1 — Downloader de pasta no navegador (sem instalação)

Este é o caminho mais curto para a maioria das pessoas, e o único que não exige nada instalado nem terminal.

  1. Abra a pasta no GitHub e confirme que o seletor de branch mostra o branch desejado.
  2. Copie a URL da barra de endereços. Ela deve se parecer com https://github.com/owner/repo/tree/main/path/to/folder — o formato /tree/<branch>/<path> importa.
  3. Cole-a no campo de URL da ferramenta da página inicial e pressione Download ZIP.
  4. Os arquivos são listados, buscados e compactados no seu navegador e depois salvos na sua pasta de Downloads.

O que separa uma boa ferramenta de uma ferramenta quebrada nesse passo não é a caixa de entrada — é o que acontece depois:

  • Branches com barras. release/2.1 é um nome de branch válido, então a ferramenta precisa testar prefixos cada vez mais longos para descobrir onde o branch termina e onde o caminho da pasta começa, em vez de chutar na primeira /.
  • Diretórios muito grandes. A Trees API retorna "truncated": true quando uma listagem recursiva ultrapassa 100.000 entradas ou 7 MB. Uma ferramenta que ignora esse sinalizador vai te entregar silenciosamente um ZIP sem arquivos. O comportamento correto é recuar para listar as subárvores um nível por vez.
  • Limites de requisições. Sem autenticação você tem 60 requisições de API por hora por endereço IP; com um token, 5.000. Ferramentas que listam diretórios um a um esgotam o orçamento não autenticado rapidamente em pastas profundas, e é por isso que os downloads às vezes falham no meio do caminho e voltam a funcionar uma hora depois.
  • Git LFS. Repositórios que usam o Large File Storage armazenam um pequeno arquivo de ponteiro no lugar do arquivo real. Se nada detectar esse ponteiro, seu ZIP fica tecnicamente correto e completamente inútil.

Para repositórios seus ou aos quais você tem acesso, cole um fine-grained personal access token no campo opcional de token: GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → gere um limitado aos repositórios específicos com Contents: Read-only. O token fica armazenado no seu próprio navegador e é enviado apenas para api.github.com; não há nenhum servidor no meio lendo os seus arquivos. Mais detalhes estão nas perguntas frequentes.

Método 2 — A rota oficial: baixar o repositório inteiro

Ainda é a resposta certa com uma frequência surpreendente, e vale conhecer as URLs diretas, porque elas pulam a interface por completo.

Pela interface: página do repositório → CodeDownload ZIP. O arquivo chega com o nome repo-main.zip (ou master, ou qualquer que seja o branch padrão).

Links diretos que você pode favoritar ou usar em scripts:

# Arquivo do branch (repositórios públicos, sem autenticação)
https://github.com/{owner}/{repo}/archive/refs/heads/{branch}.zip

# O mesmo arquivo, servido pelo host de arquivos
https://codeload.github.com/{owner}/{repo}/zip/refs/heads/{branch}

# zipball da API — funciona para repositórios privados quando você envia um token
https://api.github.com/repos/{owner}/{repo}/zipball/{ref}

Escolha isso quando o repositório for pequeno, quando você realmente quiser a maior parte dos arquivos, quando não tiver o Git instalado ou quando quiser o commit exato por trás de uma tag de release. O custo é proporcional: um monorepo de 800 MB para clonar tem cerca de 800 MB para ZIP, mais o tempo gasto extraindo e apagando os 95% de que você não precisava. E um snapshot em ZIP é só isso — um snapshot. Sem histórico, sem remote, sem git pull.

Método 3 — git sparse-checkout, feito do jeito certo

Quando você quer a pasta mais um checkout Git funcional — para poder puxar atualizações depois —, o sparse checkout é a ferramenta certa. A maioria dos tutoriais mostra uma receita desatualizada; aqui está a moderna.

git clone --filter=blob:none --sparse https://github.com/owner/repo.git
cd repo
git sparse-checkout set path/to/folder

O que importa aqui:

  • --filter=blob:none transforma o clone em um clone parcial: o Git busca os objetos de commit e de tree, mas pula o conteúdo dos arquivos até que eles sejam colocados no checkout. Sem ele, você baixa todos os blobs do repositório e descarta a maioria.
  • --sparse inicializa o arquivo de sparse-checkout para você, então não é preciso escrever .git/info/sparse-checkout à mão.
  • git sparse-checkout set usa o cone mode, que corresponde a diretórios inteiros e é drasticamente mais rápido em repositórios grandes. Adicione mais caminhos depois repetindo o comando com vários caminhos e execute git sparse-checkout reapply de novo se a árvore de trabalho sair de sincronia.
  • O sparse checkout exige o Git 2.25 ou mais novo; o clone parcial (--filter) exige a versão 2.19 ou superior.

O padrão mais antigo que você ainda vai ver em posts e respostas do Stack Overflow — git init, depois git config core.sparseCheckout true, depois echo "path/" >> .git/info/sparse-checkout, depois git pull origin main — funciona, mas baixa o histórico completo e todos os blobs antes de filtrar a árvore de trabalho. Você termina com a pasta que queria mais um diretório .git que facilmente fica várias vezes maior do que os próprios arquivos.

O trade-off real: o sparse checkout te dá um repositório, não um arquivo compactado. Se você queria um ZIP limpo para jogar em outro projeto, agora tem um checkout com um remote anexado — que é exatamente o que você queria se pretende contribuir, e puro overhead se não pretende.

Método 4 — Automatize com a API REST do GitHub

Para tarefas repetíveis — incorporar uma pasta compartilhada em outro repositório, puxar templates no CI, atualizar os assets da documentação todas as noites —, você quer algo que possa rodar sem interface. A API te dá dois blocos de construção.

Trees API (uma requisição para a subárvore inteira):

GET https://api.github.com/repos/{owner}/{repo}/git/trees/{ref}?recursive=1

A resposta contém um array plano tree com um path e um type para cada entrada. Entradas com type: "blob" são arquivos. A pegadinha é o teto documentado: com recursive=1 o array é limitado a 100.000 entradas e 7 MB e, ao ultrapassar isso, a resposta define "truncated": true. Quando isso acontece, a correção documentada é buscar a tree de forma não recursiva e percorrer as subárvores por conta própria.

Contents API (uma requisição por diretório):

GET https://api.github.com/repos/{owner}/{repo}/contents/{path}?ref={ref}

Isso retorna uma listagem com um download_url para cada arquivo, e era o que a maioria das ferramentas de navegador usava historicamente. Ela nunca trunca, mas custa uma requisição por diretório, e é por isso que árvores profundas esgotam os limites de requisições.

Um script completo e pequeno usando a Trees API mais o raw.githubusercontent.com:

OWNER=octocat
REPO=Spoon-Knife
REF=main
PREFIX=src/assets
TOKEN=""   # defina para repositórios privados: export TOKEN=ghp_xxx

AUTH=()
[ -n "$TOKEN" ] && AUTH=(-H "Authorization: Bearer $TOKEN")

# 1. Verifique se a listagem não está truncada antes de confiar nela
curl -s "${AUTH[@]}" \
  "https://api.github.com/repos/$OWNER/$REPO/git/trees/$REF?recursive=1" \
  | jq -r '.truncated'

# 2. Grave todos os caminhos de arquivo sob o prefixo em uma lista
curl -s "${AUTH[@]}" \
  "https://api.github.com/repos/$OWNER/$REPO/git/trees/$REF?recursive=1" \
  | jq -r --arg p "$PREFIX" \
    '.tree[] | select(.type == "blob") | select(.path | startswith($p + "/")) | .path' \
  > files.txt

# 3. Busque cada arquivo, criando os diretórios conforme necessário
while read -r path; do
  mkdir -p "$(dirname "$path")"
  curl -sL "${AUTH[@]}" -o "$path" \
    "https://raw.githubusercontent.com/$OWNER/$REPO/$REF/$path"
done < files.txt

Duas observações operacionais. Primeiro, fique de olho nos cabeçalhos da resposta: X-RateLimit-Remaining diz quanto orçamento resta e X-RateLimit-Reset quando ele é reabastecido — sem autenticação, esse orçamento é de 60 requisições por hora por IP, então uma pasta com 200 arquivos vai falhar no meio do caminho sem um token. Segundo, raw.githubusercontent.com respeita um cabeçalho Authorization para repositórios privados, mas você precisa de fato enviá-lo; sem ele, você recebe um 404 idêntico ao de um arquivo apagado.

Método 5 — Pegue apenas um arquivo de uma pasta

Às vezes você não precisa da pasta. Todo arquivo tem uma URL raw que baixa diretamente:

https://raw.githubusercontent.com/{owner}/{repo}/{ref}/{path}

Na interface do GitHub, abra o arquivo e clique em Raw (ou clique com o botão direito nele e escolha “Save link as…”). Adicionar ?raw=true a uma URL /blob/ normal faz a mesma coisa. Para três arquivos, isso supera qualquer ferramenta desta página.

O truque do SVN está morto — e os tutoriais ainda o recomendam

Por cerca de uma década, o conselho padrão era se apoiar na ponte de Subversion do GitHub: trocar /tree/main/ por /trunk/ na URL e rodar svn checkout ou svn export contra ela, o que fazia o checkout de um único diretório sem tocar no Git.

Essa ponte não existe mais. O GitHub anunciou o fim do suporte ao Subversion em janeiro de 2023, aplicou dois períodos de brownout em novembro e dezembro de 2023 para eliminar os usuários restantes e removeu o protocolo Subversion por completo em 8 de janeiro de 2024. O GitHub Enterprise Server seguiu o mesmo caminho na versão 3.13. Também se foi o git archive --remote, que precisa do serviço upload-archive do lado do servidor, que o GitHub nunca habilitou — o comando falha com um erro de protocolo não importa como você formate o caminho.

Se um guia lista svn checkout como primeiro método, esse guia é anterior à remoção e os outros conselhos dele também merecem análise crítica. Use o sparse checkout, a Trees API ou uma ferramenta de navegador.

Qual método você deve usar?

Método Com o que você termina Lida com repositórios privados Lida com LFS Custo principal
Downloader de pasta no navegador Um ZIP da pasta Sim, com um fine-grained token Sim, quando a ferramenta busca as mídias do LFS Exige uma URL correta e uma ferramenta que respeite o truncamento
ZIP do repositório Um ZIP do branch inteiro Sim, via zipball da API Apenas ponteiros Largura de banda e tempo escalam com o repositório, não com a pasta
git sparse-checkout Um checkout Git de verdade da pasta Sim, com credenciais Sim, com o Git LFS instalado Não é um arquivo compactado limpo; objetos Git extras
API REST + curl Exatamente os arquivos que você programou Sim, com um token Ponteiros, a menos que sejam tratados Você mantém o script e o orçamento de requisições
URLs de arquivo raw Arquivos individuais Sim, com um cabeçalho de autenticação Ponteiros, a menos que sejam tratados Manual e um arquivo por vez

Solução de problemas: as sete falhas que você realmente vai encontrar

1. Um 404 em um repositório que claramente existe. Ele é privado e a sua requisição é anônima. Envie um token. Para qualquer coisa automatizada, use um fine-grained token com escopo nos repositórios específicos e Contents definido como somente leitura, em vez de um token clássico com escopo repo amplo.

2. 403 no meio de um download longo. Você atingiu o limite de requisições da API: 60 requisições por hora sem autenticação, 5.000 com um token. O horário de reinício está no cabeçalho X-RateLimit-Reset. Autentique-se ou use uma ferramenta que liste uma subárvore inteira em uma requisição, em vez de uma por diretório.

3. O indicador de progresso nunca termina, ou o ZIP está sem arquivos. Sintoma clássico de uma listagem recursiva de tree truncada. Confirme com "truncated": true na resposta da API e depois busque as subárvores nível por nível, em vez de recursar a partir da raiz.

4. Arquivos de cerca de 130 bytes. Esses são ponteiros do Git LFS que começam com version https://git-lfs.github.com/spec/v1. O conteúdo real fica em https://media.githubusercontent.com/media/{owner}/{repo}/{ref}/{path}. Clone com o Git LFS instalado ou use uma ferramenta que troca o endpoint automaticamente.

5. O ZIP não contém a pasta que você esperava. Você está em um branch diferente do que supôs ou — com o ZIP oficial — está olhando para a raiz do branch e precisa navegar até a pasta primeiro. Verifique o seletor de branch antes de copiar a URL.

6. Pastas vazias onde deveria haver um submódulo. Submódulos são repositórios separados referenciados por uma entrada especial, não arquivos dentro do pai. Clone a URL do próprio submódulo para obter o conteúdo dele.

7. Download bloqueado ou arquivo ignorado silenciosamente. Filtros de conteúdo às vezes sinalizam nomes de arquivos, e bloqueadores de anúncios ou extensões de privacidade agressivas podem quebrar downloads paralelos. Tente novamente com as extensões desativadas para o site e confira o log de status da ferramenta para ver os nomes ignorados.

Perguntas frequentes

Consigo baixar uma pasta de um repositório privado? Sim. Todos os métodos aqui suportam isso, mas todos exigem autenticação: um personal access token com permissão de leitura em Contents para ferramentas baseadas em API, ou credenciais Git normais para um clone. Nunca cole um token de escopo amplo em um site de terceiros que você não analisou.

Baixar uma pasta preserva o histórico do Git? Não. Arquivos ZIP e downloads via API são snapshots do estado atual. Só os métodos baseados em git clone — incluindo o sparse checkout — mantêm o histórico.

Por que o meu download é muito maior do que a pasta que eu queria? Porque você baixou o ZIP do repositório em vez da pasta, ou porque a pasta contém grandes arquivos binários. Compare com o tamanho da própria pasta no GitHub antes de culpar a ferramenta.

Consigo baixar uma pasta de um branch, tag ou commit específico? Sim. O segmento de caminho depois de /tree/ é a ref, então https://github.com/owner/repo/tree/v2.1.0/path/to/folder funciona, assim como passar uma tag ou um SHA de commit para a Trees API.

Baixar código do GitHub é seguro? O transporte é, mas o conteúdo é enviado por usuários e não revisado. Verifique a licença do repositório antes de reutilizar qualquer coisa, leia o código antes de executá-lo e veja as notas de privacidade nas nossas perguntas frequentes sobre como os tokens são tratados.

Principais conclusões

  • O GitHub não consegue baixar uma única pasta porque o modelo de objetos do Git só define diretórios como trees dentro de um snapshot — a pasta é um trabalho de montagem do lado do cliente, não um recurso do servidor.
  • Para um download pontual, uma ferramenta de navegador que respeita nomes de branch, truncamento, LFS e limites de requisições concluirá a tarefa em segundos sem instalar nada.
  • Para trabalho que você vai continuar puxando, use git clone --filter=blob:none --sparse mais git sparse-checkout set — não a receita mais antiga de .git/info/sparse-checkout que baixa tudo primeiro.
  • Para automação, a Trees API lista uma subárvore inteira em uma requisição; lembre-se do teto de 100.000 entradas e do limite de 60 versus 5.000 requisições por hora.
  • Ignore qualquer guia que ainda comece com svn checkout. Esse caminho foi removido do GitHub em 8 de janeiro de 2024.

Pronto para pular a configuração? Cole a URL de uma pasta na ferramenta GitDownloader e ela vai empacotar só aquele diretório — público ou privado, LFS incluído, inteiramente no seu navegador.