mysqlclient: the MySQLdb fork Python projects still reach for
MySQL/MariaDB connector for Python
At a glance
- What is it?
- mysqlclient is a GPL-2.0 C extension that wraps the MySQL or MariaDB client library for Python. It is the drop-in MySQLdb replacement most Django deployments expect, and it makes you deal with system headers before you get a connection.
- Who is it for?
- mysqlclient is the right choice if you are running MySQL or MariaDB from CPython 3.10 or newer, you want the MySQLdb API that Django and older code already import, and you can install C client headers on every machine that builds your environment.
- Can I use it commercially?
- Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What mysqlclient actually is, and who hits the problem it solves
The README opens with the origin story: this project is a fork of MySQLdb1, and it "adds Python 3 support and fixed many bugs." That sentence is the whole pitch. If your codebase imports MySQLdb, or if a framework you use imports it on your behalf, mysqlclient is the package that keeps that import working on a modern interpreter. The project metadata requires Python 3.10 or newer, and the classifiers list 3.10 through 3.14, so this is not a compatibility shim for old runtimes.
The audience is narrower than "anyone using MySQL from Python." It is people who need the DB-API 2.0 interface backed by the actual C client library, not a reimplementation of the wire protocol. Django is the common entry point: the related searches include "mysqlclient django" and "how to install mysqlclient in django," which suggests a large share of installs happen because a Django project's database backend expects this package rather than a pure-Python driver.
If you are writing a small script that reads one table, you are not the target user. The build cost described below only pays off when you want the MySQLdb API specifically, or when you want the client library's own behavior rather than a Python reimplementation of it.
The C extension and pkg-config: how the build finds your client library
There is no Python-level protocol implementation here. mysqlclient compiles a C extension against the MySQL or MariaDB client library, and the build step is where most of the friction lives. setup.py contains a function called find_package_name that walks a fixed list of pkg-config names in order: mysqlclient, then mariadb, then libmariadb, then perconaserverclient. It calls pkg-config --exists on each and returns the first that succeeds. If none succeed, it raises an exception telling you to "Specify MYSQLCLIENT_CFLAGS and MYSQLCLIENT_LDFLAGS env vars manually."
That ordering explains a lot of platform confusion. Ubuntu ships a mariadb.pc file, while CentOS ships libmariadb.pc, as the comment in setup.py notes. Both resolve through the same fallback chain, so the same pip install can succeed on one distribution and fail on another depending on which .pc file is present and whether pkg-config itself is installed. The package layout puts the importable code under src/MySQLdb, and pyproject.toml reads the version dynamically from MySQLdb.release, so the extension and the Python package ship together.
The data flow after the build is conventional for a DB-API driver: you open a Connection, get a Cursor from it, execute a statement, and fetch rows. The C layer passes your parameters to the client library and hands back Python objects. Nothing in the README suggests connection pooling, async execution, or an ORM layer, and you should not expect any of those from this package.
Installing mysqlclient on Linux, macOS and Windows
The README gives separate paths per platform, and they are not equivalent. On Debian or Ubuntu the documented first step is the development headers and pkg-config, then pip. The README is blunt that this is a "basic step" and that you should ask on a user forum rather than filing an issue if your environment needs more.
$ sudo apt-get install python3-dev default-libmysqlclient-dev build-essential pkg-config
$ pip install mysqlclientOn Red Hat or CentOS the equivalent line is different, because the package names differ:
% sudo yum install python3-devel mysql-devel pkgconfigOn macOS with Homebrew, the README offers two variants. The first installs the full MySQL server plus pkg-config. The second avoids the server and points pkg-config at the client-only formula, which is the one to use if you connect to a remote database and do not want a local daemon running.
$ brew install mysql-client pkg-config
$ export PKG_CONFIG_PATH="$(brew --prefix)/opt/mysql-client/lib/pkgconfig"
$ pip install mysqlclientAfter a successful install you should be able to import the module and open a connection. The README does not print a connection example, so the first real use is the standard DB-API pattern: import MySQLdb, call connect with your host, user, password and database, then cursor and execute. Windows is the outlier. The README states plainly that building on Windows is "very hard" and that binary wheels are the intended route. If no wheel exists for your Python version, you must install the MariaDB C Connector in its default location, or set MYSQLCLIENT_CONNECTOR to a custom path before pip install. If that source build fails, the README says not to ask for support.
Free threading support and the single-Connection rule
Since v2.2.8 the extension supports free-threaded Python, and the README notes that importing MySQLdb therefore does not acquire the GIL. That is a real change to how the module behaves at import time, and it is marked experimental.
The more important sentence sits right next to it, in a warning block: do not use a single Connection object from multiple threads simultaneously, and the behavior in that case is undefined. This applies regardless of free threading. So the free-threading work does not turn a Connection into a thread-safe object. It removes an import-time lock, which matters for applications that want to start threads without serializing on import, and it does nothing for the shared-cursor pattern that causes corrupted results in threaded code.
If you need concurrency, the model the README implies is one Connection per thread, or a pool that hands out separate connections. The project does not ship a pool. That is a gap you fill with your own code or with another layer, and it is worth knowing before you design around this driver.
pymysql vs mysqlclient: the actual difference in approach
The related searches include "mysqlclient vs pymysql," and the distinction is architectural rather than cosmetic. mysqlclient is a C extension that links the MySQL or MariaDB client library; PyMySQL is a pure-Python implementation of the same protocol. That single difference drives most of the practical consequences.
With mysqlclient you inherit the build step: pkg-config, development headers, a compiler, and a wheel that either exists for your platform or does not. With PyMySQL you get a package that installs from pip without system dependencies, which is why it shows up in environments where you cannot install C headers, such as some managed build systems or restricted containers. The trade is that you are running a Python implementation of the client protocol rather than the vendor's C library.
Both expose a DB-API interface, and the MySQLdb API that mysqlclient provides is the older, more widely assumed one. If a framework or a legacy codebase imports MySQLdb directly, PyMySQL is not a drop-in substitute at the import line unless you add a compatibility shim. That import compatibility, not raw speed claims, is the honest reason to pick mysqlclient over PyMySQL. The README makes no performance comparison, and neither should you.
Licence and the cost of keeping it current
The project is GPL-2.0-or-later, as stated in both the repository metadata and pyproject.toml. That is a copyleft licence, and it is a different obligation from the permissive licences many Python packages carry. If you distribute software that links this extension, the GPL terms apply to that distribution. This is not legal advice, and the FSF's own guidance on linking and the GPL is the place to check how it applies to your product. Plenty of teams ship mysqlclient inside server-side applications they never distribute, where the question does not arise; teams shipping desktop or embedded binaries should look at it before they commit.
On maintenance, the last push was on 2026-09-25, and the most recent release listed is v2.3.0 from 2026-09-07. The prior releases were v2.2.8 in February 2026 and v2.2.7 in January 2025. That cadence is worth reading carefully: roughly one release a year in the 2.2.x line, then a 2.3.0 in September 2026. The repository is not archived.
Upgrade cost is mostly environmental. Because the package compiles against system client libraries, a Python upgrade, a distribution upgrade, or a switch from MySQL to MariaDB can each change which pkg-config name resolves and whether a wheel is available. The MYSQLCLIENT_CFLAGS and MYSQLCLIENT_LDFLAGS environment variables are the documented escape hatch when the automatic lookup picks the wrong library or finds none. Budget for rebuilding the extension whenever the base image changes, not just when the version number does.
Editorial conclusion
mysqlclient is the right choice if you are running MySQL or MariaDB from CPython 3.10 or newer, you want the MySQLdb API that Django and older code already import, and you can install C client headers on every machine that builds your environment. It is the wrong choice if you cannot guarantee those headers at build time, if you need a pure-Python dependency you can vendor, or if you plan to share one Connection object across threads, which the README explicitly warns against. Before adopting it, confirm the pkg-config package name your platform uses, because setup.py tries mysqlclient, then mariadb, libmariadb and perconaserverclient in that order and raises if none is found, and check whether a prebuilt wheel exists for your Python version on Windows before you attempt a source build.
Frequently asked questions
How do I install mysqlclient on Ubuntu?
Install the development headers and pkg-config first, then the package: sudo apt-get install python3-dev default-libmysqlclient-dev build-essential pkg-config, followed by pip install mysqlclient. The README describes this as a basic step and says to seek help on a user forum if your environment needs more.
How do I install mysqlclient on macOS?
With Homebrew, either install mysql and pkg-config, or install mysql-client and pkg-config and export PKG_CONFIG_PATH="$(brew --prefix)/opt/mysql-client/lib/pkgconfig" before running pip install mysqlclient. The second route avoids installing a local MySQL server.
What is the difference between pymysql and mysqlclient?
mysqlclient is a C extension built against the MySQL or MariaDB client library, while PyMySQL implements the client protocol in pure Python. That means mysqlclient needs system headers and a build step, and it provides the MySQLdb API that older code and some frameworks import directly.
How do I install mysqlclient for Django?
The install is the same as any other use: get the client development headers and pkg-config for your platform, then pip install mysqlclient. Django is one of the frameworks that expects the MySQLdb interface, which is why this package is the usual answer to that requirement.
How do I install mysqlclient in Python?
Install the MySQL or MariaDB client development headers and pkg-config for your platform, then run pip install mysqlclient. The package requires Python 3.10 or newer according to its project metadata.
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/pymysql-mysqlclient)