PictShare v3: a file based image host where the URL does the resizing
:camera: PictShare is an open source image, mp4, pastebin hosting service with a simple resizing and upload API that you can host yourself. :rice_scene:
At a glance
- What is it?
- PictShare is a self hostable PHP service for images, GIFs, MP4s, audio and text pastes, where resizing, conversion and filtering are encoded in the URL rather than in an API call, and no database is required. It fits people who want one container to own their media, and it does not fit multi-tenant teams that need quotas and per-user accounts.
- Who is it for?
- Adopt PictShare when you want a single container that owns uploaded media, resizes it on demand through the URL, and keeps everything on disk without a database, and accept that the transform happens on the PHP host you run. Do not adopt it for multi-tenant use, since the roadmap still shows UPLOAD_QUOTA, LOW_PROFILE, IMAGE_CHANGE_CODE and MAX_RESIZED_IMAGES unchecked, and per-user accounts do not exist.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
PictShare encodes resize, filter and format in the URL path
PictShare is a self hostable service for images, gifs, mp4s and text bins, and the mechanism that defines it is that the URL is the interface. Change and resize your images and videos just by editing the URL, as the feature list puts it. A path segment selects the operation and a later segment carries the file name.
Two of the newer features show how expressive that is. Placeholder images are generated by specifying the size in the URL, for example a path of /placeholder/555x250/color-white-blue. Identicons are generated based on strings in the URL, so /identicon/example1 returns an avatar derived from the text. Neither requires an uploaded file. The same URL grammar carries filters, MP4 resizing and format conversion.
The reason this matters is that a conventional image host would return a fixed file and offer you a resize parameter at request time, or pre-generate thumbnails. PictShare instead treats the transformation as part of the address of the resource, which makes the result cacheable and shareable, and makes the service feel like a content-addressed store rather than an application with a menu of endpoints.
The audience is people running their own infrastructure who want an image and pastebin service they control, and the project is explicit about the appeal: full control over your data, with individual and global delete codes. There is no hosted plan to buy and no account system to manage, so the operator is the only user, plus anyone given a link.
100 percent file based, so there is no database to run or migrate
The architectural decision that shapes everything else is stated in the feature list: 100 percent file based, no database needed. There is no schema, no ORM and no connection string to configure, which means a PictShare instance is a directory of files plus a PHP application in front of them.
That has direct consequences for how you back up and how you scale. A backup is a file copy, and the project points to a scaling document for the details of running several instances. The same simplicity explains why duplicate uploads cost nothing: if the exact same file is uploaded twice, the second upload links to the first, so the bytes are stored once and both references resolve to the same file.
Deletion follows the same model. Every uploaded file gets a delete code, and there is a MASTER_DELETE_CODE to remove all files plus a MASTER_DELETE_IP, an address allowed to delete everything even without a code. Those two settings are the core of the deletion model, and they are the reason it is simple enough to trust and blunt enough to configure carefully.
The repository layout matches this. There are src/ and web/ directories for the application, a data/ directory for the stored files, configs/ for configuration, tests/ with a phpunit.xml, and an rtfm/ directory that holds the reference documents the project links to, including INSTALL.md, CONFIG.md, DOCKER.md, API.md, SCALING.md and MCP.md.
v3 broke the URL rule and moved the API to a REST shape
If you are upgrading from an earlier PictShare, the project puts a caution notice on the front page: Pictshare v3 may not be fully compatible with previous Pictshare versions. The changes are specific and worth reading before you point a client at a new instance.
The structural change is that the file name must now be the last part of the URL. In older versions the file name could sit anywhere in the path, so a rotated image was requested at a path of /roate-left/1234.png/800x600/. In v3 the operation and the size come first and the file name comes last, so the same resource is requested at /roate-left/600x600/1234.png. Any script that builds URLs by string concatenation has to change, and any link you shared before the upgrade stops resolving.
The API moved at the same time to a more consistent and RESTful design, with the API documentation updated to match. Three configuration options were dropped outright: TITLE, UPLOAD_FORM_LOCATION and ALLOW_BLOATING. Dropping UPLOAD_FORM_LOCATION is worth a second look if you relied on it, since the compose file still exposes an environment variable of that name, and the same variable is listed as checked in the configuration checklist. That inconsistency between the release note and the shipped configuration surface is a small but real trap during a migration.
The larger v3 work was described as a code rework, with the goal of a more modular and easier to debug design. The features added on top of that base include text hosting like a pastebin, Markdown rendering that converts .md files to HTML, audio support for mp3, wav, ogg, flac and m4a with a player, and WebP support with automatic conversion from jpg and png when the requesting browser supports it.
Docker in one command, with the security knobs set to safe defaults
The quick start is a single container run, and the port mapping is the only thing you need to change for a local trial.
docker run -d -p 8080:80 --name=pictshare ghcr.io/hascheksolutions/pictshareYou then open http://localhost:8080 in your browser. The image is also published on Docker Hub as hascheksolutions/pictshare, and the compose file in the repository pins a versioned tag, HaschekSolutions/pictshare:3, rather than a floating one.
Most of the compose file is environment variables, and the security-relevant ones are worth reading in full before you expose the instance. ADMIN_PASSWORD is the password for the admin panel, and if it is empty the admin panel is disabled. UPLOAD_CODE, when set, requires that code to upload files through the API or the web form. ALLOWED_SUBNET restricts upload and admin access to an IP address or subnet mask. MASTER_DELETE_CODE and MASTER_DELETE_IP control global deletion, and UPLOAD_FORM_LOCATION moves the upload form away from the root path.
One setting deserves a separate warning because the compose file itself carries it. HTML_HOSTING_ENABLED=false is marked DANGER in the file: enabling it lets holders of HTML_UPLOAD_CODE serve arbitrary HTML and JavaScript on your domain, so the project asks you to read rtfm/CONFIG.md before switching it on.
environment:
- URL=http://localhost:8080/
- MAX_UPLOAD_SIZE=20 #in MB
- ADMIN_PASSWORD= # password for the admin panel. if empty, admin panel is disabled
- ALLOWED_SUBNET= #IP address or subnet mask to allow upload and access to the admin panel
- UPLOAD_CODE= # if set, requires this code to upload files via api or webOther settings cover storage and processing: S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY, S3_ENDPOINT and S3_REGION for the external storage backend, FTP settings for a second destination, ENCRYPTION_KEY for encrypting files in external storage, and FFMPEG_BINARY, PNG_COMPRESSION, JPEG_COMPRESSION and WEBP_COMPRESSION for the conversion pipeline. LOG_VIEWS and REDIS_CA handle logging and caching.
An MCP endpoint so agents can upload and delete without a human
PictShare v3 ships a built-in Model Context Protocol endpoint at POST /mcp using Streamable HTTP, and the point of it is that an agent can manage files through the same operations a person would use in the browser.
Registering an instance in Claude Code is a single command.
claude mcp add --transport http pictshare https://your.pictshare.host/mcpIf your instance sets UPLOAD_CODE, clients have to send it as a bearer token in the Authorization header, otherwise the upload tools will be rejected by the same code that guards the API.
The exposed tools map onto the features above. upload_from_url downloads a remote URL and stores it, upload_base64 takes base64 encoded content, get_file_info returns metadata such as mime type, size, sha1 and upload time, delete_file deletes a file using its delete code, create_album combines hashes into an album, and transform_image builds a resized, filtered or rotated image URL. The album tool matches the album feature, which combines multiple uploads into a single immutable gallery URL.
This is the part of PictShare that has no equivalent in a plain static host, and it is also the part with the most operational weight. An agent that can upload and delete through your instance inherits whatever you set in UPLOAD_CODE, MASTER_DELETE_CODE and HTML_HOSTING_ENABLED, so those values are the security boundary for the whole endpoint, not just for the web form.
Roadmap gaps, exif stripping, and a licence to read carefully
The development roadmap is unusually honest, because every item is either checked or not. Duplicate detection, write permission detection, delete codes for every uploaded file, upload via link, upload via base64 and the album feature are all marked done. Autodestruct for every uploaded file is not. In the configuration list, UPLOAD_QUOTA, LOW_PROFILE, IMAGE_CHANGE_CODE, MAX_RESIZED_IMAGES and ALLOW_BLOATING are unchecked, and URL shortening is listed under its own heading with the upload of links to shorten still open.
Those gaps define the ceiling on multi-user use. There is no upload quota, so one client can fill your disk, and there is no low profile mode to hide the admin panel or restrict what may be uploaded beyond the CONTENTCONTROLLERS allow list. If you put an instance on the public internet with an open upload form, you are exposing an unauthenticated disk to anyone who finds the URL.
One privacy feature does deserve credit, because it is the kind of detail that leaks by default. PictShare removes all exif data, so GPS tags and camera model information are wiped when you upload photos from your phone.
On the licence, be careful. The licence field on the repository says a custom licence that GitHub cannot classify, and points you to the LICENSE file, while the badge in the project documentation is an Apache badge. Those two statements do not obviously agree, so read the LICENSE file yourself before you redistribute an instance or a derivative work. None of this is legal advice. For maintenance, the repository is not archived and the last push was on 2026-10-19, but there are no GitHub releases at all, so the CHANGELOG.md in the repository is where version history lives.
Editorial conclusion
Adopt PictShare when you want a single container that owns uploaded media, resizes it on demand through the URL, and keeps everything on disk without a database, and accept that the transform happens on the PHP host you run. Do not adopt it for multi-tenant use, since the roadmap still shows UPLOAD_QUOTA, LOW_PROFILE, IMAGE_CHANGE_CODE and MAX_RESIZED_IMAGES unchecked, and per-user accounts do not exist. Before deploying, confirm the file name is the last part of every URL as v3 requires, read the LICENSE file rather than the Apache badge on the project page, and set UPLOAD_CODE or ADMIN_PASSWORD before the instance is reachable from the internet.
Frequently asked questions
How do I run PictShare quickly?
Run the published container with docker run -d -p 8080:80 --name=pictshare ghcr.io/hascheksolutions/pictshare and then open http://localhost:8080 in your browser. The image is also available on Docker Hub as hascheksolutions/pictshare.
Does PictShare need a database?
No. The feature list describes PictShare as 100 percent file based with no database needed, and stored uploads live in a data/ directory, so backing up an instance means copying files.
What changed in PictShare v3?
The file name must now be the last part of the URL, where older versions allowed it anywhere in the path, and the API moved to a more consistent RESTful design. The configuration options TITLE, UPLOAD_FORM_LOCATION and ALLOW_BLOATING were dropped.
How do I restrict uploads on my PictShare instance?
Set UPLOAD_CODE so that uploads through the API or web form require a code, set ADMIN_PASSWORD to enable the admin panel, and use ALLOWED_SUBNET to limit upload and admin access to an address or subnet. Keep HTML_HOSTING_ENABLED false unless you have read rtfm/CONFIG.md.
Can an AI agent upload to PictShare?
Yes, through the built-in Model Context Protocol endpoint at POST /mcp, which exposes tools such as upload_from_url, upload_base64, get_file_info, delete_file, create_album and transform_image. If UPLOAD_CODE is set, clients must send it as a bearer token.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hascheksolutions-pictshare)Was this useful?