Chris Collins

Tools · cloud

Data-lake browser

Browse and query object stores and HDFS from the browser — S3, MinIO, R2, B2, Wasabi, GCS, Azure Blob and WebHDFS/HttpFS: buckets and folders, uploads with resumable multipart, Range downloads, presigned URLs, Parquet/ORC/Avro schema and row-group statistics, DuckDB SQL over files, HDFS block locations, bucket CORS/policy/lifecycle generators, and the aws/mc/gcloud/az/hdfs command and curl for every action.

Added

How to use it

One workspace for the files of a data lake, wherever they sit: S3-compatible object stores, Google Cloud Storage, Azure Blob Storage and HDFS. Pick a bucket, walk its folders, look inside a Parquet file’s row groups without downloading it, run SQL over a few files, upload a 2 GB export in resumable parts, and copy the exact aws s3, mc, gcloud storage, az storage or hdfs dfs command for what you just did. It opens on a demo bucket that lives in the page (CSV, NDJSON, JSON, Parquet, Avro, ORC and an image), so everything can be tried without an account.

How to use it

  1. Connection — choose one, or + New and ✎ Edit:

    • S3 profile in the gitwebsite app (recommended). The gitwebsite app (or gw serve) signs each request itself with a profile you add once — gw companion s3 add lab --endpoint http://192.168.1.20:9000 --region us-east-1 --path-style and gw companion secret set s3:lab — so the keys stay in the macOS Keychain and the bucket needs no CORS. Press ⚡ Use the gitwebsite app and approve the code in the app. Through the app you can list, read (with Range), upload up to 100 MB per file, delete (confirmed in the app), copy (by reading and writing again) and presign; multipart, versions and bucket settings need a direct connection.

    • S3-compatible, keys in this page — Amazon S3, MinIO, Cloudflare R2, Backblaze B2, Wasabi, GCS with HMAC keys, or any other S3 API. Requests are signed here with AWS Signature Version 4 (WebCrypto); the keys are kept in the page’s memory and gone when you close it, unless you tick Remember (stored unencrypted in this browser — a warning says so). The bucket must allow this page with CORS: Generators → CORS gives the exact rules for each provider, and Bucket → PutBucketCors applies them where you may.

    • Google Cloud Storage — the JSON API with an OAuth access token (gcloud auth print-access-token), and a project id to list buckets or the bucket names.

    • Azure Blob — a SAS URL for the account (lists containers) or one container; it needs l and r, and w, c, d to change things. CORS is set on the storage account.

    • HDFS — the namenode’s WebHDFS (http://namenode:9870) or HttpFS (:14000), directly (the cluster then needs the Hadoop cross-origin filter, shown under Generators → CORS → HDFS) or through the gitwebsite app (relay/lan: no CORS; the app asks you the first time the page reaches a new LAN host). Simple authentication (user.name=) or a delegation token. Datanode addresses rewrites the datanode names in WebHDFS’s redirects for clusters in Docker or Kubernetes (dn1:9864=10.0.0.21:9864).

  2. Browse — the tree on the left lists buckets (containers, the HDFS root) and the folders you have opened; the list pages through ListObjectsV2 continuation tokens (Azure markers, GCS page tokens, WebHDFS LISTSTATUS_BATCH) with Load more. Starts with… searches by key prefix on the server; Filter this page narrows what is listed; click a column to sort (folders first). Tick rows to delete several at once; + Folder creates a prefix; drop files on the browser or ⇪ Upload to upload into the open folder.

  3. Click a file. Info shows the size, ETag (and what a multipart ETag means), storage class, content type, user metadata, versions, and for HDFS the owner, permissions, replication, block size, the blocks along the file with their datanodes (GETFILEBLOCKLOCATIONS), and a replication setter. Preview shows text, CSV (delimiter detected), JSON, NDJSON and images, read with a Range request (the first 256 KB) — gzip files are inflated when small. Schema reads only the footer of Parquet (FileMetaData: schema with logical types, every row group and column chunk with codec, encodings, compressed and uncompressed sizes, min/max statistics and null counts), the tail of ORC (types, stripes, column statistics; ZLIB and Snappy footers) and the header and first blocks of Avro (writer schema, codec, rows). Commands lists the CLI equivalents for the file and the last request as curl.

  4. Actions: Download (8 MB Range reads with progress; big S3 files through a presigned URL), Presigned URL with your choice of expiry (1 s – 7 days), Copy, Move / rename (S3 copy
    delete; WebHDFS RENAME), Query in SQL, Delete (always confirmed).

  5. SQL — DuckDB-wasm in a worker. ▶ Query in SQL adds a file under its name; a query that names it fetches it (up to 200 MB) the first time. On a direct S3 connection, Parquet over 32 MB is read by Range through a presigned URL, so DuckDB fetches only the footer and the columns a query needs. Examples include parquet_metadata(), parquet_schema() and SUMMARIZE. Export the result as CSV, JSON or Parquet. The demo’s files can be queried by name (SELECT * FROM 'cities.csv').

  6. Bucket — the bucket’s location, versioning, CORS, policy and lifecycle (S3 direct, GCS), each with its CLI command; for HDFS the folder’s content summary and quotas.

  7. Generators — bucket CORS for Amazon S3, MinIO (one server-wide setting), Cloudflare R2, Backblaze B2 (native rules with s3_* operations), Wasabi, GCS, Azure and Hadoop, with the command that applies it; a least-privilege IAM policy (read-only, read-write or write-only, scoped to a prefix with an s3:prefix condition on ListBucket); bucket policies (deny non-TLS, public read of a prefix, read for one role); lifecycle rules (transition, expiry, old versions, abort incomplete multipart uploads).

  8. Transfers — uploads and downloads with progress and speed. S3 files over 16 MB go up as multipart uploads (8 MiB parts, four at a time, raised so a file fits in 10,000 parts); Pause lets the running parts finish, Resume carries on, and an upload interrupted by a reload resumes when you choose the same file again (the upload id and part ETags are kept in this browser). Azure uploads over 16 MB use Put Block / Put Block List the same way.

  9. Requests — every request the page made (signatures and tokens masked) and Copy as curl: SigV4 requests use curl --aws-sigv4 with $AWS_ACCESS_KEY_ID / $AWS_SECRET_ACCESS_KEY, the app’s requests $GW_COMPANION_TOKEN, Azure $AZURE_SAS_SIG — never the secret itself.

⛶ Full screen (or F) gives the browser the whole screen; ◫ Panels hides the connection panel.

Limits

  • Kerberos (SPNEGO) clusters are out of scope: a browser page cannot do the Kerberos handshake for WebHDFS. Use a delegation token from a Kerberized gateway, or HttpFS behind a proxy that authenticates.

  • ORC rows are not decoded (DuckDB-wasm has no ORC reader) — only the schema, stripes and statistics. Avro rows are decoded for the null, deflate and snappy codecs; Parquet’s and ORC’s ZSTD and LZ4 footers are fine (footers are not compressed in Parquet), ORC footers compressed with ZSTD/LZ4 are not read.

  • GCS presigned URLs need a service-account private key, which the page does not take (the gcloud storage sign-url command is shown). GCS uploads are single requests.

  • Through the gitwebsite app: uploads up to 100 MB, no multipart, versions or bucket settings (the app’s relay/s3 refuses them); WebHDFS writes and reads through the app need the datanodes reachable from the app’s computer too.

  • Direct mode is only as good as the store’s CORS: a hidden ETag header breaks multipart uploads, a missing Range in AllowedHeaders breaks previews and DuckDB’s Range reads.

  • Folder deletes and renames work object by object (S3 DeleteObjects in batches of 1,000), so a large prefix takes a while; S3 copy is single-request (objects up to 5 GB).

  • Secrets you choose to remember are stored unencrypted in this browser’s localStorage.

Tested against the AWS SigV4 test suite and the S3 API reference’s signing examples (headers and presigned URLs), Parquet/ORC/Avro fixtures written by pyarrow 26, DuckDB 1.5 and fastavro 1.13, and live against MinIO and an Apache Hadoop 3 namenode, datanode and HttpFS — directly and through the gitwebsite app’s companion (relay/s3 and relay/lan).

Linking to an example

Share link copies the generator settings and the SQL editor’s query (never connections, keys, tokens or SAS URLs). Put the tab after #: browse, sql, bucket, generate, transfers or requests.

Parameter Meaning Example

example

a preset (below)

example=cors-r2

sql

the query in the SQL editor

sql=SELECT%201

gen

generator: cors, iam, bucket or lifecycle

gen=iam

provider

CORS generator provider: aws, minio, r2, b2, wasabi, gcs, azure, hdfs

provider=b2

origins

allowed origins, space-separated

origins=https%3A%2F%2Fexample.org

bucket

bucket for the generators

bucket=my-lake

prefix

prefix for the IAM policy, bucket policy or lifecycle rule

prefix=curated%2F

access

IAM policy access: read, readwrite, write

access=readwrite

open

a demo file to open (bucket/key)

open=demo-lake%2Fraw%2Fcities.csv

Presets:

Runs entirely in your browser — network requests go only to the services named on this page.