# gpt4free's cookie directory is the credential, and its two Docker guides disagree on the UID

> GPT4Free is a GPL-3.0 Python client that puts several model providers behind an OpenAI-compatible API, a web GUI and a JavaScript client. The mechanics matter more than the feature list here. Some providers are reached with your own browser session rather than a key, the install asks you to mount a cookie directory into the container, the two documented Docker setups chown that directory to different user IDs, and the slim image installs packages on every start.

**xtekky/gpt4free** — The official gpt4free repository | various collection of powerful language models | opus 4.6 gpt 5.3 kimi 2.5 deepseek v3.2 gemini 3

- Repository: https://github.com/xtekky/gpt4free
- Website: https://t.me/g4f_channel
- Stars: 66,736 · Forks: 13,497
- Language: Python
- License: GPL-3.0
- Published: 2026-08-17 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/xtekky-gpt4free

## The project answers to four different names in four different namespaces

The repository is xtekky/gpt4free. The README credits it as created by @xtekky and maintained by @hlohaus. The package on PyPI is named `g4f`, the container image is `hlohaus789/g4f`, and the Windows launcher lives in a third organisation at github.com/gpt4free/g4f.exe. The documentation sits at g4f.dev.

Then there is the repository's own declared homepage, which is a Telegram channel rather than any of those. The quick links list points at the website, the docs, PyPI, the Docker Hub image, the releases, the issues, and both a Telegram channel and two Discord servers.

The consequence is that there is no single canonical location, and the mismatches are specific rather than cosmetic. The Windows guide tells you to download `g4f.exe.zip` from the xtekky/gpt4free releases but run a launcher whose code lives under the gpt4free organisation. The Docker image you pull is published by the maintainer's account, not the repository owner. And the homepage field points at a chat channel while the README's own documentation link is the website.

If you are filing an issue or looking for a release, check which namespace the thing belongs to before you search, or you will spend time in a repository that does not contain it.

## The credential for browser-backed providers is your own cookie jar

Look at what the packaging asks for. The install extras include `browser_cookie3`, annotated in setup.py with the comment get_cookies. Alongside it sit aiohttp_socks annotated for proxy support and ddgs annotated for web search. The extras exist to give the adapters the ability to act as a signed-in browser rather than as an anonymous API caller.

The Docker instructions make that concrete. You create two directories, one called har_and_cookies and one called generated_media, chown them, and mount both into the container. The page also says port 7900 can expose a VNC-like desktop for provider logins, which is how you complete a login interactively inside a headless container, and that Chrome or Chromium is required for the providers that use browser automation.

So the thing being protected is your browser session, and the setup asks you to hand that directory to a container. The consequence is that har_and_cookies should be treated as a credential store rather than as a cache: anyone who can read it can act as you on the sites whose cookies are in it, and the cookies are the durable part, not the container.

Two things are worth noting about what the page does not tell you. It does not document a rotation or revocation procedure for that directory, and it does not say which providers use cookies rather than keys. If you need to know what a given adapter is doing, the provider documentation is where the page sends you, and it says so.

## The two documented Docker setups chown the cookie directory to different UIDs

The recommended full-image setup begins by creating the two directories and changing their owner:

```bash
mkdir -p ${PWD}/har_and_cookies ${PWD}/generated_media
sudo chown -R 1200:1201 ${PWD}/har_and_cookies ${PWD}/generated_media
```

The slim-image setup does the same two things with different numbers and without sudo:

```bash
mkdir -p ${PWD}/har_and_cookies ${PWD}/generated_media
chown -R 1000:1000 ${PWD}/har_and_cookies ${PWD}/generated_media
```

Two documented paths, two owner pairs, and the blocks are near enough identical that the difference is easy to miss when you are copying one to the other.

The consequence is a confusing first run. If you follow the full-image instructions and then pull the slim image, or the reverse, the container cannot write to the mounted volumes, and the error you get points at the cookie or media directory rather than at a user ID mismatch. Match the chown block to the image tag you actually pulled rather than to the one you read first. Note also that the full setup needs sudo and the slim one does not, which is a second small signal that they are aimed at different container users.

Both setups also raise the shared memory limit, passing `--shm-size="2g"` in the run command, and the page says to increase it for heavier browser automation. That is not cosmetic: a browser-backed provider on the default shared memory size is a common way to see these containers fail.

## The slim image installs packages on startup, so its tag does not describe the code

The slim image section contains one sentence that changes how you should think about pinning it: the slim image can update the g4f package on startup and installs additional dependencies as needed.

So `hlohaus789/g4f:latest-slim` describes a base image, not the program that will be running inside it. The package version is resolved at container start.

The consequence is that the property you normally get from a pinned image, that the same tag always produces the same behaviour, does not hold here. Two containers started from the same tag on different days can run different versions of the library and different sets of dependencies, and the mutation happens inside the container every time it starts rather than at image build time. Rolling back does not mean re-pulling a tag, because the tag did not determine the version in the first place; it means rebuilding or pinning explicitly.

The slim instructions also map two host ports to the same container port, `-p 1337:8080 -p 8080:8080`, and say that the Interference API is mapped to 1337. Two host ports serving one container port is not wrong, since the API and the GUI can share a listener, but it is worth knowing which one your client should point at before you conclude something is not listening.

## docker-compose mounts your whole checkout over the application directory

The compose file that ships with the repository declares a build context, a Dockerfile, an image tag, three published ports and one volume:

```yaml
    volumes:
      - .:/app
    ports:
      - '8080:8080'
      - '1337:8080'
      - '7900:7900'
    environment:
      - OLLAMA_HOST=host.docker.internal
```

That single volume line is the one to look at. Mounting `.` over `/app` means the code that executes is your working copy, not the version baked into the image, so in this setup the image tag is close to decorative.

The consequence runs in both directions. What runs is whatever is in your directory, which is useful when you are editing the project and misleading when you think you are running a published release. And anything the container deletes under `/app` lands in your checkout, in the same parent directory as the cookie and media mounts. Both `image` and `build` are declared at the same time, so what compose actually does depends on which of the two invocations you use.

The environment line is the interesting one for local inference: pointing `OLLAMA_HOST` at `host.docker.internal` is how a container reaches a model server running on the host, which is the mechanism behind the local inference support the README describes.

## The core install is five packages, and the all extra adds a WebAssembly runtime with no explanation

setup.py splits requirements into a small core and a set of extras. The core install list is five packages: requests, aiohttp, brotli, pycryptodome and nest-asyncio2.

Everything else is an extra. The `all` group adds around two dozen more, including browser_cookie3, ddgs, beautifulsoup4, aiohttp_socks, pillow, cairosvg, werkzeug, flask with the async extra, fastapi, uvicorn, a2wsgi, markitdown with all of its own extras, numpy, pystray and cryptography. Smaller groups exist for image, api and gui.

The important detail is that the extras are not nested. The `slim` group is not `all` with things removed: it drops cairosvg, markitdown, wasmtime and numpy, and adds pypdf2 and python-docx instead. So choosing a smaller install changes which capabilities you have rather than which version of them.

Two consequences. A bare `pip install g4f` gives you a client core with no GUI, no API server and no image support, so the capability you actually want is an extra you have to name. And the repository carries three requirements files, requirements-min.txt, requirements-slim.txt and requirements.txt, while the from-source instructions use requirements.txt, the middle one, so a source install does not obviously match any of the extras either. One loose end: wasmtime, a WebAssembly runtime, appears in the `all` group and the page never says what it is for.

## setup.py deletes GitHub alert markers so the PyPI page differs from the README

One line in setup.py explains a difference you will notice if you read both pages:

```python
long_description = long_description.replace("[!NOTE]", "")
```

The README uses GitHub's alert syntax for its callouts. That syntax does not render on a package index, so the packaging step strips the marker text out of the long description rather than converting the callout into something the index can show.

The consequence is small but it changes what you are reading. The PyPI page and the GitHub page are not the same document. Any alert block that appears on GitHub is missing its marker on PyPI, and if the callout's content was inside the marker rather than after it, the content goes too. So if you install from PyPI and then read the repository to understand a warning, you may find the warning is not where you expected it.

The same line is a useful marker for how the project is maintained. It is the kind of detail that only exists because someone hit the rendering problem and fixed it in the build rather than in the prose, which is a reasonable trade for a project publishing to both surfaces.

## A takedown policy sits next to the GPL licence, so the provider set is not a fixed asset

The repository ships LEGAL_NOTICE.md and SECURITY.md alongside the GPL-3.0 LICENSE, and the README has a table of contents section titled security, privacy and takedown policy. There is also a CODE_OF_CONDUCT.md, a CONTRIBUTING.md, a SKILL.md and an example.env at the top level, alongside a g4f-go/ directory, which means a Go implementation sits in the same tree as the Python one.

The takedown policy is the part that has practical consequences for anyone building on this. It exists because the project anticipates that a provider can ask for access to be removed, which makes the provider list a moving target rather than a fixed capability set. An adapter you depend on can disappear between releases.

The release cadence makes that more likely rather than less. Three patch versions landed in the three days to 2026-09-22, v8.5.6, v8.5.7 and v8.5.8, with the last push to main on the same date as the newest tag. Fast releases are good for fixes and bad for pinning, and combined with a provider set that can be reduced on request, they mean you should verify that the specific adapter you need still exists in the version you pin.

On the legal question, the code is GPL-3.0 and the repository carries a separate legal notice, but the page does not offer a position on any individual provider's terms, and nothing here should be read as advice. Read LEGAL_NOTICE.md and the terms of the service you are reaching through, then decide.

## Conclusion

Adopt gpt4free when you want one OpenAI-compatible endpoint across several providers and you are willing to manage a browser session as the credential. Do not adopt it expecting a key-based service, because for the browser-backed providers the secret is your cookie jar and the install says so. Four things to settle first. Which image you run, since the full and slim guides chown the cookie directory to different UIDs and copying the wrong block fails on the mounted volume rather than telling you the UID is wrong. Whether you can accept a container that reads your browser cookies, and if so treat the har_and_cookies directory as a credential store with no documented rotation procedure. Whether you need reproducibility, because the slim image installs packages on startup so its tag does not describe the code that runs. And which version you pin, since three patch releases landed in the three days to 2026-09-22 and the provider set is not guaranteed stable. Read LEGAL_NOTICE.md and the takedown policy before deploying it anywhere that matters.

## FAQ

### Is gpt4free really free?

The code is free and licensed GPL-3.0, distributed on PyPI as `g4f` and as a Docker image you can pull without a paid tier. What the project supplies is not model access of its own: it describes itself as a community-driven project that aggregates multiple accessible providers and interfaces. So the software costs nothing while the upstream providers keep their own terms, and the page states no cost, quota or service level for any of them.

### Is gpt4free legal to use?

The repository is licensed GPL-3.0 and ships a separate LEGAL_NOTICE.md, and the README has a section on its security, privacy and takedown policy. The page does not state a position on any individual provider's terms of service, and whether a given adapter is permitted is a question about that provider rather than about this project. Read the legal notice and the provider's own terms; nothing here is advice on the question.

### Is gpt4free safe to install?

The credential surface is the thing to weigh. The install extras include browser_cookie3 for reading cookies, the Docker instructions have you create and mount a directory called har_and_cookies, and port 7900 is offered to expose a desktop for completing provider logins. The Windows guide also tells you to allow the application through the firewall. The repository ships a SECURITY.md, and the cookie directory is the part to protect.

### How do you use gpt4free?

There are four surfaces. Install with `pip install -U g4f[all]`, or run the container with `docker run -p 8080:8080 -p 7900:7900 --shm-size="2g"` and the two mounted directories. The web GUI is served on port 8080, with the chat page at localhost:8080/chat/. The FastAPI-based OpenAI-compatible endpoint is called the Interference API, mapped to port 1337 in the slim example, and there are Python, async Python and browser JavaScript clients.

### Does gpt4free have a VS Code extension?

The project page says nothing about Visual Studio Code, and there is no extension in what it documents. What it does offer is an OpenAI-compatible REST API, which is the integration point an editor would use: point any client that speaks the OpenAI API shape at the Interference API address instead of at a hosted endpoint. The page also lists a Flask-based web GUI and a separate local inference option reached through an OLLAMA_HOST setting.

## Sources

- [Official documentation](https://t.me/g4f_channel)
- [Official README](https://github.com/xtekky/gpt4free#readme)
- [Project repository](https://github.com/xtekky/gpt4free)
- [Release notes](https://github.com/xtekky/gpt4free/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/xtekky-gpt4free
