diff --git a/.gitattributes b/.gitattributes
index b3d70ca8b24fbfcceb82421f71ee3eeae1822c10..f77da2339b20f84b889e7f4e2e9ade20ae15341c 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -85,4 +85,5 @@ pandas/tests/io/parser/data export-ignore
 
 # Include cibw script in sdist since it's needed for building wheels
 scripts/cibw_before_build.sh -export-ignore
-scripts/cibw_before_test.sh -export-ignore
+scripts/cibw_before_build_windows.sh -export-ignore
+scripts/cibw_before_test_windows.sh -export-ignore
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 212ce7441dfab6bd83df3b96b1ab7de5c421457f..07fb0c19262a161695c0b677debe335cff821f65 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -387,8 +387,8 @@ jobs:
       - name: Build Environment
         run: |
           python --version
-          python -m pip install --upgrade pip setuptools wheel meson[ninja]==1.2.1 meson-python==0.13.1
-          python -m pip install --pre --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy cython
+          python -m pip install --upgrade pip setuptools wheel numpy meson[ninja]==1.2.1 meson-python==0.13.1
+          python -m pip install --pre --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple cython
           python -m pip install versioneer[toml]
           python -m pip install python-dateutil pytz tzdata hypothesis>=6.84.0 pytest>=7.3.2 pytest-xdist>=3.4.0 pytest-cov
           python -m pip install -ve . --no-build-isolation --no-index --no-deps -Csetup-args="--werror"
diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml
index 4bff9e7e090daf8b52133ffbeaf76c9f0ffda900..354402c572adea860fc1f68263f1f30cde679d83 100644
--- a/.github/workflows/wheels.yml
+++ b/.github/workflows/wheels.yml
@@ -111,10 +111,6 @@ jobs:
         - buildplat: [ubuntu-22.04, pyodide_wasm32]
           python: ["cp312", "3.12"]
           cibw_build_frontend: 'build'
-        # TODO: Build free-threaded wheels for Windows
-        exclude:
-        - buildplat: [windows-2022, win_amd64]
-          python: ["cp313t", "3.13"]
 
     env:
       IS_PUSH: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
@@ -181,20 +177,6 @@ jobs:
         shell: bash -el {0}
         run: for whl in $(ls wheelhouse); do wheel unpack wheelhouse/$whl -d /tmp; done
 
-      # Testing on windowsservercore instead of GHA runner to fail on missing DLLs
-      - name: Test Windows Wheels
-        if: ${{ matrix.buildplat[1] == 'win_amd64' }}
-        shell: pwsh
-        run: |
-          $TST_CMD = @"
-          python -m pip install hypothesis>=6.84.0 pytest>=7.3.2 pytest-xdist>=3.4.0;
-          python -m pip install `$(Get-Item pandas\wheelhouse\*.whl);
-          python -c `'import pandas as pd; pd.test(extra_args=[`\"--no-strict-data-files`\", `\"-m not clipboard and not single_cpu and not slow and not network and not db`\"])`';
-          "@
-          # add rc to the end of the image name if the Python version is unreleased
-          docker pull python:${{ matrix.python[1] == '3.13' && '3.13-rc' || format('{0}-windowsservercore', matrix.python[1]) }}
-          docker run --env PANDAS_CI='1' -v ${PWD}:C:\pandas python:${{ matrix.python[1] == '3.13' && '3.13-rc' || format('{0}-windowsservercore', matrix.python[1]) }} powershell -Command $TST_CMD
-
       - uses: actions/upload-artifact@v4
         with:
           name: ${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}
diff --git a/MANIFEST.in b/MANIFEST.in
index a7d7d7eb4e062d125a33c9b97372a46f5ea0933d..c59151f3405451ea86737ce122cb5d02db98718c 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -65,3 +65,5 @@ graft pandas/_libs/include
 
 # Include cibw script in sdist since it's needed for building wheels
 include scripts/cibw_before_build.sh
+include scripts/cibw_before_build_windows.sh
+include scripts/cibw_before_test_windows.sh
diff --git a/pyproject.toml b/pyproject.toml
index 6dfee8f4910db17eee89e2c8bab78871ce3a27f0..0c76ecd0b15b4c55b7d366f13550b781c7af1a90 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -160,7 +160,13 @@ free-threaded-support = true
 before-build = "PACKAGE_DIR={package} bash {package}/scripts/cibw_before_build.sh"
 
 [tool.cibuildwheel.windows]
-before-build = "pip install delvewheel && bash {package}/scripts/cibw_before_build.sh"
+before-build = "pip install delvewheel && bash {package}/scripts/cibw_before_build_windows.sh"
+before-test = "bash {package}/scripts/cibw_before_test_windows.sh"
+test-command = """
+  set PANDAS_CI='1' && \
+  python -c "import pandas as pd; \
+  pd.test(extra_args=['--no-strict-data-files', '-m not clipboard and not single_cpu and not slow and not network and not db']);" \
+  """
 repair-wheel-command = "delvewheel repair -w {dest_dir} {wheel}"
 
 [[tool.cibuildwheel.overrides]]
@@ -175,13 +181,6 @@ test-command = """
 select = "*-musllinux*"
 before-test = "apk update && apk add musl-locales"
 
-[[tool.cibuildwheel.overrides]]
-select = "*-win*"
-# We test separately for Windows, since we use
-# the windowsservercore docker image to check if any dlls are
-# missing from the wheel
-test-command = ""
-
 [[tool.cibuildwheel.overrides]]
 # Don't strip wheels on macOS.
 # macOS doesn't support stripping wheels with linker
diff --git a/scripts/cibw_before_build.sh b/scripts/cibw_before_build.sh
index 679b91e3280ec071b2cc6cdda626487f8fda6a15..4cdbf8db0ba89492f8ce973608247a7fd933fc09 100644
--- a/scripts/cibw_before_build.sh
+++ b/scripts/cibw_before_build.sh
@@ -5,8 +5,8 @@ done
 
 # TODO: Delete when there's a PyPI Cython release that supports free-threaded Python 3.13.
 FREE_THREADED_BUILD="$(python -c"import sysconfig; print(bool(sysconfig.get_config_var('Py_GIL_DISABLED')))")"
-if [[ $FREE_THREADED_BUILD == "True"  ]]; then
+if [[ $FREE_THREADED_BUILD == "True" ]]; then
     python -m pip install -U pip
-    python -m pip install -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy cython
-    python -m pip install ninja meson-python versioneer[toml]
+    python -m pip install -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple cython
+    python -m pip install numpy ninja meson-python versioneer[toml]
 fi
diff --git a/scripts/cibw_before_build_windows.sh b/scripts/cibw_before_build_windows.sh
new file mode 100644
index 0000000000000000000000000000000000000000..5153ebd691f3b106d21e016c2a722781e6bbdf6b
--- /dev/null
+++ b/scripts/cibw_before_build_windows.sh
@@ -0,0 +1,13 @@
+# Add 3rd party licenses, like numpy does
+for file in $PACKAGE_DIR/LICENSES/*; do
+  cat $file >> $PACKAGE_DIR/LICENSE
+done
+
+# TODO: Delete when there's a PyPI Cython release that supports free-threaded Python 3.13
+# and a NumPy Windows wheel for the free-threaded build on PyPI.
+FREE_THREADED_BUILD="$(python -c"import sysconfig; print(bool(sysconfig.get_config_var('Py_GIL_DISABLED')))")"
+if [[ $FREE_THREADED_BUILD == "True" ]]; then
+    python -m pip install -U pip
+    python -m pip install -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy cython
+    python -m pip install ninja meson-python versioneer[toml]
+fi
diff --git a/scripts/cibw_before_test_windows.sh b/scripts/cibw_before_test_windows.sh
new file mode 100644
index 0000000000000000000000000000000000000000..dd02bc23dd5a17841deb5c2ee7a0898b7a88acbd
--- /dev/null
+++ b/scripts/cibw_before_test_windows.sh
@@ -0,0 +1,5 @@
+# TODO: Delete when there's a NumPy Windows wheel for the free-threaded build on PyPI.
+FREE_THREADED_BUILD="$(python -c"import sysconfig; print(bool(sysconfig.get_config_var('Py_GIL_DISABLED')))")"
+if [[ $FREE_THREADED_BUILD == "True" ]]; then
+    python -m pip install -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy
+fi