
Website Content Crawler
scrape.ly/store/querystone/website-content-crawlerAIDeveloper tools
1 monthly user

Turn public GitHub repositories into one LLM-ready Markdown or XML document: directory tree, every source file in language-tagged code fences, exact token counts. Branches, folders, glob filters. No token or login needed.
Turn any public GitHub repository into one clean, LLM-ready document: a directory tree followed by every source file in a language-tagged code fence, with an exact token count. Paste it into ChatGPT, Claude, Gemini or your own agent, or feed it to a RAG pipeline. No GitHub token, no login, and a typical repository is done in seconds.
node_modules, vendor, dist, build output, lockfiles, minified bundles, source maps, images and other binaries, so your context window holds code, not junk.o200k_base tokenizer (GPT-4o family), so you know before you paste whether it fits./tree/main/src), and .gitignore-style include and exclude patterns..md (or .xml) file with a download link, and the dataset can hold the text, a compact summary, or one row per file.docs/ folder into one file for summarising or translating.https://github.com/owner/repo, owner/repo, or a folder link such as https://github.com/owner/repo/tree/main/src).| Field | What it does |
|---|---|
repoUrls | Public GitHub repositories, one per line. Folder and branch links work too, and so does owner/repo@tag. |
ref | Branch, tag or commit for repositories whose URL does not name one. |
subdirectory | Only convert this folder, e.g. src. |
includePatterns / excludePatterns | .gitignore-style globs, e.g. *.py, src/**, tests/. |
maxFileSizeKb | Skip files larger than this (default 256 KB). |
skipBinaries, skipLockfiles, skipVendored | Noise filters, all on by default. |
maxFilesPerRepo, maxTokensPerRepo | Stop adding files at a file or token budget. maxFilesPerRepo caps file rows; the repository summary row comes on top. |
outputFormat | markdown (default) or xml (<file path="..."> tags). |
includeTree, lineNumbers | Directory tree at the top; line numbers in code. |
datasetRows | document (default), summary (compact, no text), files or both. |
maxTokensPerPart | Split each document into rows of at most this many tokens. |
{
"repoUrls": [
"https://github.com/pallets/itsdangerous",
"https://github.com/psf/requests/tree/main/src/requests"
],
"excludePatterns": ["tests/", "docs/"],
"datasetRows": "document"
}
One row per repository (or per part, for very large repositories):
| Field | Description |
|---|---|
repository, repoUrl | owner/repo and its URL |
ref, commitSha | Branch or tag, and the exact commit converted |
subdirectory | Folder, when you chose one |
fileCount, totalFilesInRepo | Files in the document, and files in scope before filtering |
skippedFiles | Counts per reason: vendored, lockfiles, binary, too large, patterns, limits |
tokenEstimate | Tokens in the whole document (o200k_base) |
languageTokens | Tokens per language, largest first |
documentUrl, documentKey, documentSizeBytes | Download link and size of the full .md / .xml file |
part, totalParts, filesInPart, partTokenEstimate | Part information when a document is split |
content | The document text (empty in summary mode) |
truncated, truncatedReason | Set when a file or token limit cut the document short |
{
"type": "repository",
"repository": "pallets/itsdangerous",
"repoUrl": "https://github.com/pallets/itsdangerous",
"ref": "main",
"commitSha": "672971d66a2ef9f85151e53283113f33d642dabd",
"subdirectory": null,
"fileCount": 46,
"totalFilesInRepo": 50,
"tokenEstimate": 25513,
"truncated": false,
"skippedFiles": {"lockfiles": 1, "binary": 3, "vendoredOrGenerated": 0, "tooLarge": 0, "excludedByPattern": 0},
"tokenizer": "o200k_base",
"documentSizeBytes": 103190,
"documentKey": "pallets-itsdangerous-main.md",
"documentUrl": "https://api.scrape.ly/v2/key-value-stores/<store>/records/pallets-itsdangerous-main.md?signature=<signature>",
"format": "markdown",
"languageTokens": {"python": 13620, "rst": 5442, "yaml": 2104, "toml": 1294, "markdown": 785},
"convertedAt": "2026-10-16T00:29:38+00:00",
"part": 1,
"totalParts": 1,
"filesInPart": 46,
"partTokenEstimate": 25513,
"content": "# pallets/itsdangerous\n\n- Repository: https://github.com/pallets/itsdangerous\n- Ref: main (commit 672971d66a2e)\n- Files: 46 | Estimated tokens: 25,513\n\n## Directory structure\n\n```\nitsdangerous/\n├── .devcontainer/\n│ ├── devcontainer.json\n...\n```\n\n## Files\n\n### `README.md`\n\n```markdown\n# ItsDangerous\n..."
}
With datasetRows set to files or both, you also get one row per file (type: file) with path, language, lines, sizeBytes, tokenEstimate, a GitHub url pinned to the commit, and content. Each repository still gets its own type: repository row (the summary in files mode, the document in both mode), so files with maxFilesPerRepo 10 returns up to 11 rows per repository: 1 repository row plus at most 10 file rows.
A repository that fails (not found, wrong branch, nothing matched your filters) saves no row. It is listed under failedInputs (input, reason) in the run's OUTPUT record and named in the status message.
You pay $0.012 per repository converted plus $0.0005 per 10,000 tokens of output ($0.05 per million tokens), plus a little platform usage.
Repositories that fail (not found, wrong branch, nothing matched your filters) are never charged. Set Max tokens per repository to cap the cost of very large repositories.
Do I need a GitHub token or account? No. Public repositories are downloaded as an archive straight from GitHub, without the API.
Does it work with private repositories? No, only public ones.
How big can a repository be? Archives up to 300 MB by default (adjustable up to 2 GB). Documents larger than about 3 MB are split into several dataset rows; the download link always holds the complete file.
Which token count is it? Exact counts for OpenAI's o200k_base tokenizer. Other models (Claude, Gemini, Llama) tokenise differently, usually within about 10 to 20%.
What if a file is missing from the document? Check skippedFiles: it counts every file left out and why. Turn off a filter or raise the size limit to include it.
Can I schedule it or call it from code or an AI agent? Yes. Use the API, schedules or the MCP server; summary mode keeps responses small and gives the agent a download link.
Every field below can be set in the run form, passed through the API, or saved as a task. Unset fields fall back to the defaults shown.
repoUrlsarrayRequiredGitHub repositories
Public GitHub repositories, one per line: https://github.com/owner/repo, owner/repo, or a folder or branch link such as https://github.com/owner/repo/tree/main/src. Each repository becomes one context document.
refstringOptionalBranch, tag or commit
Optional. Used for every repository that does not name one in its URL. Leave empty for the default branch.
subdirectorystringOptionalSubdirectory
Optional folder inside each repository, e.g. src or packages/core. A /tree// URL overrides it.
Choose which files go into the document.
includePatternsarrayOptionalInclude patterns
Optional glob patterns (.gitignore syntax). Only matching files are kept, e.g. *.py, src/**, docs/**/*.md.
excludePatternsarrayOptionalExclude patterns
Optional glob patterns to drop, e.g. tests/, **/*.test.ts, *.snap, examples/**.
maxFileSizeKbintegerOptionaldefault 256Max file size (KB)
Skip files larger than this. Big files are usually generated data, fixtures or bundles.
skipBinariesbooleanOptionaldefault trueSkip binary files and images
Leave out images (including SVG), fonts, archives, media and other non-text files. Turn off to list them with a placeholder line.
skipLockfilesbooleanOptionaldefault trueSkip lockfiles
Leave out package-lock.json, yarn.lock, pnpm-lock.yaml, poetry.lock, Cargo.lock, go.sum and similar files.
skipVendoredbooleanOptionaldefault trueSkip vendored, build and minified files
Leave out node_modules, vendor, dist, build, target, .venv, __pycache__ and similar folders, plus *.min.js, source maps and snapshots.
maxFilesPerRepointegerOptionaldefault 5000Max files per repository
Stop adding files after this many (0 = no limit). The document says when it was truncated. With Dataset rows set to Files or Both, this caps the file rows per repository; the repository row comes on top (10 gives up to 11 rows per repository).
maxTokensPerRepointegerOptionaldefault 0Max tokens per repository
Stop adding files once the document would pass this many tokens (0 = no limit). Handy to fit a model's context window and to cap the cost.
Shape of the document and the dataset rows.
outputFormatenumOptionaldefault "markdown"Document format
Markdown uses a heading and a language-tagged code fence per file. XML wraps each file in tags, which some models follow more reliably.
includeTreebooleanOptionaldefault trueDirectory tree
Start the document with a tree of the included files.
lineNumbersbooleanOptionaldefault falseLine numbers
Prefix every line of code with its line number (useful for code review prompts; adds tokens).
datasetRowsenumOptionaldefault "document"Dataset rows
The full document is always saved to the key-value store with a download link. Choose what the dataset holds. 'Summary only' keeps the output compact for AI agents.
maxTokensPerPartintegerOptionaldefault 0Max tokens per part
Split each document into dataset rows of at most this many tokens, at file boundaries (0 = split only when a row would pass the dataset size limit, about 3 MB).
maxArchiveSizeMbintegerOptionaldefault 300Max archive size (MB)
Skip repositories whose compressed archive is larger than this.
maxConcurrencyintegerOptionaldefault 3Parallel repositories
How many repositories to download at the same time.
proxyConfigurationobjectOptionaldefault {"useScrapelyProxy":true,"scrapelyProxyGroups":["DATACENTER…Proxy configuration
Downloads go through rotating datacenter proxies to spread GitHub's rate limits. Most users never need to change this.
Every run writes its results to a dataset. Preview it in the dashboard, then export it or read it through the API.
| Field | Type | Description |
|---|---|---|
| repository | any | Repository |
| ref | any | Ref |
| subdirectory | any | Folder |
| part | any | Part |
| totalParts | any | Parts |
| fileCount | any | Files |
| tokenEstimate | any | Tokens |
| documentUrl | any | Download |
| truncated | any | Truncated |
| commitSha | any | Commit |
You pay for the events the actor reports, such as each result or page it produces. Platform usage is included in the event prices.
| Event | Charged when | Price |
|---|---|---|
| Repository converted | One GitHub repository (or folder) converted into an LLM context document. Failed repositories are free. | $0.012 |
| 10,000 tokens of output | Charged per started block of 10,000 tokens in each converted document (o200k_base tokenizer). | $0.0005 |
Run this actor from your own code. Swap in your API token and the examples work as-is.
import { ScrapelyClient } from 'scrapely-client'
const client = new ScrapelyClient({ token: process.env.SCRAPELY_TOKEN })
// Start the actor and wait for the run to finish.
const run = await client.actor('querystone/github-repo-to-markdown').call({
"repoUrls": [
"https://github.com/pallets/itsdangerous",
"https://github.com/psf/requests/tree/main/src/requests"
],
"proxyConfiguration": {
"useScrapelyProxy": true,
"scrapelyProxyGroups": [
"DATACENTER"
]
}
})
// Read the dataset the run produced.
const { items } = await client.dataset(run.defaultDatasetId).listItems()
console.log(items)Tokens live in your account settings. Keep them server-side: a token carries the full permissions of your account.
Connect the Scrape.ly MCP server once and your agent can run this actor as a tool. Pick your tool:
Fetch scrape.ly/agents.md and run querystone/github-repo-to-markdownPaste into Claude Code, Codex, Cursor or any AI agent. It signs you in once in the browser.
{
"mcpServers": {
"scrapely": {
"url": "https://api.scrape.ly/mcp?tools=actors,runs,storage,docs&actors=querystone/github-repo-to-markdown"
}
}
}No key in the file: your client opens the browser to sign you in the first time it connects.
Inputs the developer prepared for common jobs. Open one to see its input, then copy it to your account to run it as-is or adjust it.
Convert GitHub repositories into one LLM-ready context file.
One row per matching file, filtered by pattern.
Scrape.ly gives you the infrastructure, the tooling, and the team to extract, process, and operationalize web data at any scale. Setup takes minutes. The advantage lasts forever.