serpapi 1.0.2__tar.gz → 1.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. serpapi-1.1.1/.readthedocs.yaml +27 -0
  2. serpapi-1.1.1/CONTRIBUTING.md +183 -0
  3. {serpapi-1.0.2 → serpapi-1.1.1}/HISTORY.md +15 -0
  4. serpapi-1.1.1/MANIFEST.in +7 -0
  5. {serpapi-1.0.2/serpapi.egg-info → serpapi-1.1.1}/PKG-INFO +47 -19
  6. {serpapi-1.0.2 → serpapi-1.1.1}/README.md +40 -18
  7. serpapi-1.1.1/assets/serpapi-icon.png +0 -0
  8. serpapi-1.1.1/assets/serpapi-logo.svg +15 -0
  9. serpapi-1.1.1/docs/Makefile +20 -0
  10. serpapi-1.1.1/docs/_static/custom.css +99 -0
  11. serpapi-1.1.1/docs/ai-agents.md +33 -0
  12. serpapi-1.1.1/docs/conf.py +41 -0
  13. serpapi-1.1.1/docs/examples/amazon-product-search.md +37 -0
  14. serpapi-1.1.1/docs/examples/baidu-search.md +35 -0
  15. serpapi-1.1.1/docs/examples/bing-search.md +40 -0
  16. serpapi-1.1.1/docs/examples/categories/ai-answers.md +7 -0
  17. serpapi-1.1.1/docs/examples/categories/finance-trends-and-jobs.md +10 -0
  18. serpapi-1.1.1/docs/examples/categories/local-and-maps.md +8 -0
  19. serpapi-1.1.1/docs/examples/categories/media-apps-and-research.md +11 -0
  20. serpapi-1.1.1/docs/examples/categories/search-engines.md +10 -0
  21. serpapi-1.1.1/docs/examples/categories/shopping-and-marketplaces.md +12 -0
  22. serpapi-1.1.1/docs/examples/categories/travel-and-hospitality.md +8 -0
  23. serpapi-1.1.1/docs/examples/duckduckgo-search.md +35 -0
  24. serpapi-1.1.1/docs/examples/ebay-product-listings.md +36 -0
  25. serpapi-1.1.1/docs/examples/google-across-countries.md +73 -0
  26. serpapi-1.1.1/docs/examples/google-ai-overview.md +46 -0
  27. serpapi-1.1.1/docs/examples/google-finance-market-data.md +40 -0
  28. serpapi-1.1.1/docs/examples/google-flights-travel.md +45 -0
  29. serpapi-1.1.1/docs/examples/google-images-search.md +37 -0
  30. serpapi-1.1.1/docs/examples/google-jobs-listings.md +39 -0
  31. serpapi-1.1.1/docs/examples/google-lens-image-upload.md +44 -0
  32. serpapi-1.1.1/docs/examples/google-local-services.md +37 -0
  33. serpapi-1.1.1/docs/examples/google-maps-local-business.md +38 -0
  34. serpapi-1.1.1/docs/examples/google-news-monitoring.md +38 -0
  35. serpapi-1.1.1/docs/examples/google-play-store-apps.md +38 -0
  36. serpapi-1.1.1/docs/examples/google-scholar-research.md +36 -0
  37. serpapi-1.1.1/docs/examples/google-shopping-price-monitoring.md +43 -0
  38. serpapi-1.1.1/docs/examples/google-shopping-products.md +39 -0
  39. serpapi-1.1.1/docs/examples/google-trends-demand.md +41 -0
  40. serpapi-1.1.1/docs/examples/home-depot-product-search.md +36 -0
  41. serpapi-1.1.1/docs/examples/index.md +205 -0
  42. serpapi-1.1.1/docs/examples/tripadvisor-travel-search.md +37 -0
  43. serpapi-1.1.1/docs/examples/walmart-product-search.md +38 -0
  44. serpapi-1.1.1/docs/examples/youtube-video-search.md +36 -0
  45. serpapi-1.1.1/docs/index.md +163 -0
  46. serpapi-1.1.1/docs/reference.md +8 -0
  47. serpapi-1.1.1/docs/requirements.txt +1 -0
  48. serpapi-1.1.1/docs/user_guide/account-and-locations.md +47 -0
  49. serpapi-1.1.1/docs/user_guide/async-search-archive.md +59 -0
  50. serpapi-1.1.1/docs/user_guide/client-usage.md +178 -0
  51. serpapi-1.1.1/docs/user_guide/errors-and-timeouts.md +81 -0
  52. serpapi-1.1.1/docs/user_guide/getting-started.md +136 -0
  53. serpapi-1.1.1/docs/user_guide/index.md +29 -0
  54. serpapi-1.1.1/docs/user_guide/json-restrictor.md +137 -0
  55. serpapi-1.1.1/docs/user_guide/migrating-from-google-search-results.md +114 -0
  56. serpapi-1.1.1/docs/user_guide/multiprocessing.md +74 -0
  57. serpapi-1.1.1/docs/user_guide/output-formats.md +57 -0
  58. serpapi-1.1.1/docs/user_guide/pagination.md +86 -0
  59. serpapi-1.1.1/docs/user_guide/parameters-and-engines.md +82 -0
  60. serpapi-1.1.1/docs/user_guide/request-options.md +137 -0
  61. serpapi-1.1.1/docs/user_guide/threading.md +74 -0
  62. serpapi-1.1.1/docs/user_guide/zero-trace.md +47 -0
  63. {serpapi-1.0.2 → serpapi-1.1.1}/pyproject.toml +11 -1
  64. serpapi-1.1.1/scripts/check_docs_revision.py +53 -0
  65. serpapi-1.1.1/scripts/publish_docs.py +207 -0
  66. serpapi-1.1.1/serpapi/__version__.py +1 -0
  67. {serpapi-1.0.2 → serpapi-1.1.1}/serpapi/core.py +69 -45
  68. {serpapi-1.0.2 → serpapi-1.1.1}/serpapi/http.py +3 -1
  69. {serpapi-1.0.2 → serpapi-1.1.1}/serpapi/models.py +9 -9
  70. {serpapi-1.0.2 → serpapi-1.1.1/serpapi.egg-info}/PKG-INFO +47 -19
  71. serpapi-1.1.1/serpapi.egg-info/SOURCES.txt +108 -0
  72. serpapi-1.1.1/serpapi.egg-info/requires.txt +15 -0
  73. serpapi-1.1.1/serpapi.egg-info/top_level.txt +1 -0
  74. {serpapi-1.0.2 → serpapi-1.1.1}/tests/conftest.py +15 -0
  75. serpapi-1.1.1/tests/docs_example_support.py +161 -0
  76. serpapi-1.1.1/tests/example_search_google_light_test.py +12 -0
  77. serpapi-1.1.1/tests/test_docs_example_runner.py +124 -0
  78. serpapi-1.1.1/tests/test_docs_examples.py +26 -0
  79. serpapi-1.1.1/tests/test_docs_publishing.py +288 -0
  80. serpapi-1.1.1/tests/test_image_upload.py +101 -0
  81. serpapi-1.1.1/tests/test_integration.py +163 -0
  82. serpapi-1.1.1/tests/test_output_formats.py +52 -0
  83. serpapi-1.0.2/MANIFEST.in +0 -2
  84. serpapi-1.0.2/docs/conf.py +0 -69
  85. serpapi-1.0.2/serpapi/__version__.py +0 -1
  86. serpapi-1.0.2/serpapi.egg-info/SOURCES.txt +0 -43
  87. serpapi-1.0.2/serpapi.egg-info/requires.txt +0 -7
  88. serpapi-1.0.2/serpapi.egg-info/top_level.txt +0 -4
  89. serpapi-1.0.2/tests/example_search_google_events_test.py +0 -12
  90. serpapi-1.0.2/tests/test_integration.py +0 -94
  91. {serpapi-1.0.2 → serpapi-1.1.1}/LICENSE +0 -0
  92. {serpapi-1.0.2 → serpapi-1.1.1}/serpapi/__init__.py +0 -0
  93. {serpapi-1.0.2 → serpapi-1.1.1}/serpapi/exceptions.py +0 -0
  94. {serpapi-1.0.2 → serpapi-1.1.1}/serpapi/textui.py +0 -0
  95. {serpapi-1.0.2 → serpapi-1.1.1}/serpapi/utils.py +0 -0
  96. {serpapi-1.0.2 → serpapi-1.1.1}/serpapi.egg-info/dependency_links.txt +0 -0
  97. {serpapi-1.0.2 → serpapi-1.1.1}/setup.cfg +0 -0
  98. {serpapi-1.0.2 → serpapi-1.1.1}/tests/__init__.py +0 -0
  99. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_apple_app_store_test.py +0 -0
  100. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_baidu_test.py +0 -0
  101. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_bing_test.py +0 -0
  102. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_duckduckgo_test.py +0 -0
  103. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_ebay_test.py +0 -0
  104. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_google_autocomplete_test.py +0 -0
  105. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_google_images_test.py +0 -0
  106. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_google_jobs_test.py +0 -0
  107. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_google_local_services_test.py +0 -0
  108. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_google_maps_test.py +0 -0
  109. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_google_play_test.py +0 -0
  110. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_google_scholar_test.py +0 -0
  111. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_google_test.py +0 -0
  112. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_home_depot_test.py +0 -0
  113. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_naver_test.py +0 -0
  114. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_walmart_test.py +0 -0
  115. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_yahoo_test.py +0 -0
  116. {serpapi-1.0.2 → serpapi-1.1.1}/tests/example_search_youtube_test.py +0 -0
  117. {serpapi-1.0.2 → serpapi-1.1.1}/tests/test_exceptions.py +0 -0
  118. {serpapi-1.0.2 → serpapi-1.1.1}/tests/test_timeout.py +0 -0
@@ -0,0 +1,27 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-24.04
5
+ tools:
6
+ python: "3.13"
7
+ jobs:
8
+ pre_build:
9
+ - python -m scripts.check_docs_revision
10
+ post_build:
11
+ - python -m scripts.check_docs_revision
12
+
13
+ sphinx:
14
+ configuration: docs/conf.py
15
+ fail_on_warning: true
16
+
17
+ formats:
18
+ - pdf
19
+ - epub
20
+
21
+ python:
22
+ install:
23
+ - method: uv
24
+ command: pip
25
+ path: .
26
+ extras:
27
+ - docs
@@ -0,0 +1,183 @@
1
+ # Contributing
2
+
3
+ Bug reports and pull requests are welcome on GitHub. Run commands from the repository root.
4
+
5
+ ## Development setup
6
+
7
+ Use Python 3.13 to work on the package and its documentation. The SDK CI also tests Python 3.8 through 3.14. Create a virtual environment and install the package with its test and documentation dependencies:
8
+
9
+ ```sh
10
+ uv venv --python 3.13
11
+ uv pip install -e '.[test,docs]'
12
+ ```
13
+
14
+ The editable install uses the Python files in your checkout, so source changes take effect without reinstalling the package.
15
+
16
+ Activate the environment on macOS or Linux:
17
+
18
+ ```sh
19
+ source .venv/bin/activate
20
+ ```
21
+
22
+ On Windows PowerShell:
23
+
24
+ ```powershell
25
+ .\.venv\Scripts\Activate.ps1
26
+ ```
27
+
28
+ The commands below use `python` from that environment.
29
+
30
+ ## Testing
31
+
32
+ ### Checks that need no API key
33
+
34
+ These tests cover response parsing, image uploads with simulated responses, timeouts, exceptions, documentation syntax, and the example runner:
35
+
36
+ ```sh
37
+ python -m pytest tests/test_output_formats.py tests/test_image_upload.py tests/test_timeout.py tests/test_exceptions.py tests/test_docs_examples.py tests/test_docs_example_runner.py -k 'not live' -q
38
+ ```
39
+
40
+ The file list limits this command to tests that make no external requests. Applying `-k 'not live'` to the entire suite is not enough to run offline: some SDK integration tests do not have `live` in their names.
41
+
42
+ ### SDK integration tests
43
+
44
+ Set `API_KEY` in your shell or editor's run configuration before running integration tests. Documentation examples also accept `SERPAPI_KEY`, but the shared SDK fixtures require `API_KEY`. If you already have `SERPAPI_KEY` set, copy it to `API_KEY` in the same shell:
45
+
46
+ ```sh
47
+ export API_KEY="$SERPAPI_KEY"
48
+ ```
49
+
50
+ In PowerShell, use `$env:API_KEY = $env:SERPAPI_KEY`. Keep real keys out of source files and commits.
51
+
52
+ To match the test selection in the SDK CI workflow:
53
+
54
+ ```sh
55
+ python -m pytest tests --ignore-glob='tests/test_docs_*.py' -k 'not example' -q
56
+ ```
57
+
58
+ This includes live account, location, search, and pagination checks. To run every discovered test, including the standalone engine examples and documentation examples:
59
+
60
+ ```sh
61
+ python -m pytest -q
62
+ ```
63
+
64
+ Both commands make real SerpApi requests. The full suite can use more searches than a test run limited to the files you changed. PR CI also runs the standalone engine examples on Python 3.14. Documentation tests run only in the package and documentation release workflows, on release tags.
65
+
66
+ ### Testing documentation examples
67
+
68
+ The tests discover Python code blocks in the README and all Markdown pages under `docs/`. They run each page as a separate script against SerpApi, including the multiprocessing example's worker processes. The Lens upload examples use the repository's PNG icon as `image.png`. Each page has a five-minute limit, and HTTP errors or JSON responses containing an `error` fail the check even if the example catches the exception.
69
+
70
+ With `SERPAPI_KEY` or `API_KEY` set in your environment, run:
71
+
72
+ ```sh
73
+ python -m pytest tests/test_docs_examples.py --require-docs-key -q
74
+ ```
75
+
76
+ The `--require-docs-key` option fails if neither key is set. Without that option, local runs skip live tests when no key is available. To check syntax and the test runner without making API calls:
77
+
78
+ ```sh
79
+ python -m pytest tests/test_docs_examples.py tests/test_docs_example_runner.py -k 'not live' -q
80
+ ```
81
+
82
+ Code blocks marked with `docs-test: skip` are checked for syntax but not executed. These cover the old `google-search-results` package and examples that require private proxy or certificate settings, or disable TLS verification. Each marker includes its reason.
83
+
84
+ ### Testing documentation publishing
85
+
86
+ Run the publishing tests locally with:
87
+
88
+ ```sh
89
+ python -m pytest tests/test_docs_publishing.py -q
90
+ ```
91
+
92
+ These tests use simulated RTD responses to check outgoing HTTP requests, CI event and commit checks, version selection, polling, and cleanup after failures. They need no API keys and do not publish documentation. In CI, they run only in the Documentation workflow on Python 3.13, before the documentation build and publication. The SDK and PyPI release workflows exclude this file. RTD checks the actual checkout with `scripts.check_docs_revision` before and after building, without rerunning the publishing tests.
93
+
94
+ ### Running a single test or example
95
+
96
+ Run one test file while working on that part of the package:
97
+
98
+ ```sh
99
+ python -m pytest tests/test_output_formats.py -q
100
+ ```
101
+
102
+ To list documentation test IDs without running their examples:
103
+
104
+ ```sh
105
+ python -m pytest tests/test_docs_examples.py --collect-only -q
106
+ ```
107
+
108
+ For example, run only the Google Lens upload and search page with:
109
+
110
+ ```sh
111
+ python -m pytest 'tests/test_docs_examples.py::test_documentation_examples_live[docs/examples/google-lens-image-upload.md]' --require-docs-key -q
112
+ ```
113
+
114
+ Use `-x -vv` in place of `-q` to stop at the first failure and show more detail. A syntax failure points to a page and block number. A live failure can come from the example code, an invalid key, exhausted quota, or an upstream API error; inspect the reported engine and error before changing the example.
115
+
116
+ When adding a documentation example, use a fenced block labelled `python`. Blocks on the same page execute in order and share variables. Avoid hard-coded dates that expire. Use a `docs-test: skip` marker with a reason only when a block cannot run in the test environment, such as one requiring a user's proxy or certificate.
117
+
118
+ ## Building the documentation locally
119
+
120
+ The documentation uses Sphinx with MyST for Markdown pages and the Read the Docs theme. The development setup above includes its dependencies. Build and serve the HTML site with:
121
+
122
+ ```sh
123
+ python -m sphinx -M html docs docs/_build -W --keep-going
124
+ python -m http.server 8000 --bind 127.0.0.1 --directory docs/_build/html
125
+ ```
126
+
127
+ Open [the local documentation](http://127.0.0.1:8000). After editing a page, rerun the Sphinx build command and refresh your browser. Check the affected page, its code blocks, and the sidebar links. Press Ctrl+C to stop the server.
128
+
129
+ Sphinx discovers public APIs with autodoc and reads their docstrings without running the search examples. Sidebar order comes from the toctrees in `docs/index.md`, so documentation filenames do not need numeric prefixes. The `-W` option makes warnings fail the build.
130
+
131
+ CI also builds EPUB. Check it locally with:
132
+
133
+ ```sh
134
+ python -m sphinx -M epub docs docs/_build -W --keep-going
135
+ ```
136
+
137
+ ## Building the package
138
+
139
+ Build the source distribution and wheel with:
140
+
141
+ ```sh
142
+ uv build
143
+ ```
144
+
145
+ The files are written to `dist/`. Documentation sources, this guide, and the logo assets are included in the source distribution (`.tar.gz`) so contributors can build the docs from a source release. The wheel contains only the `serpapi` library and its package metadata. Generated docs and documentation dependencies are not part of a normal installation.
146
+
147
+ ## Documentation publishing
148
+
149
+ The [documentation workflow](.github/workflows/docs.yml) runs the live examples before building HTML and EPUB when a `v*` release tag is pushed or selected for a manual run. It does not run on branch pushes or pull requests.
150
+
151
+ After the live examples and documentation build pass, the same workflow publishes to Read the Docs for the selected release tag. The publishing job uses the `docs` GitHub environment and its `RTD_API_TOKEN` secret. The SerpApi key stays in GitHub as the existing `API_KEY` repository or organization secret.
152
+
153
+ The workflow syncs RTD versions, activates the requested version if needed, and waits for the build to finish. `latest` tracks `master`. A release tag has its own version and also updates `stable` when RTD identifies it as the highest stable release. RTD still builds the site from the repository using [.readthedocs.yaml](.readthedocs.yaml); it does not receive the HTML artifact from GitHub. Documentation publishing runs independently of the PyPI release workflow.
154
+
155
+ Before requesting a build, the workflow creates a temporary RTD environment variable named `DOCS_CI_REVISION`. It contains the tested commit, the permitted versions, and an expiration time. RTD checks this record against its checkout before and after the Sphinx build. A missing, expired, or different revision stops publication. RTD needs no SerpApi key. The workflow removes the temporary record after publishing, including when a build fails. Publishing jobs run one at a time so they cannot overwrite each other's revision record.
156
+
157
+ ### Maintainer setup
158
+
159
+ Maintainers can configure the existing RTD project and GitHub environment with these steps:
160
+
161
+ 1. In RTD **Settings**, set **Connected repository** to **No connected repository** and keep **Repository URL** set to `https://github.com/serpapi/serpapi-python.git`. Set **Default branch** to `master` and the configuration file path to `.readthedocs.yaml`. The public repository URL lets RTD clone the source without receiving GitHub push events through the GitHub App.
162
+ 2. Under RTD **Integrations**, remove incoming GitHub webhook integrations for this project. If an older RTD webhook is also listed in the GitHub repository's **Settings > Webhooks**, disable or remove that webhook. Do not remove integrations for other projects.
163
+ 3. Under RTD **Automation Rules**, remove rules that activate new versions or change the default version. The workflow handles release activation. Under **Settings > Pull request builds**, turn off **Build pull requests for this project**. GitHub Actions runs the existing SDK and engine example tests on PRs.
164
+ 4. Under RTD **Environment Variables**, remove `API_KEY` or `SERPAPI_KEY` if you added either for docs tests. Do not add the RTD API token here. The workflow manages `DOCS_CI_REVISION` automatically.
165
+ 5. Keep `latest` active in **Versions** and use it as the default documentation version during this migration. Existing release tags contain their original docs and build configuration. After the first release containing these changes builds successfully, you can choose `stable` as the default version.
166
+ 6. Create an RTD API token in your [RTD profile settings](https://app.readthedocs.org/accounts/tokens/), using an account that maintains the `serpapi-python` project. In GitHub, open the repository's **Settings > Environments**, create an environment named `docs`, and add an environment secret named `RTD_API_TOKEN` with that value. Under **Deployment branches and tags**, select **Selected branches and tags** and add a Tag rule for `v*`. Leave required reviewers and wait timers disabled if publishing should run without a manual approval.
167
+ 7. Merge the changes to `master`, then push the version tag for the release. In GitHub **Actions > Documentation**, follow **Live documentation examples**, **Build Sphinx documentation**, and **Publish Read the Docs**. The publishing log links to the RTD build. To retry publishing, run the Documentation workflow on the intended release tag. A manual run on a branch skips the documentation jobs.
168
+
169
+ Use GitHub Actions to request builds after this setup. A manual RTD build has no CI revision record and will fail the revision check. If a branch or tag moves between testing and the RTD checkout, rerun the workflow for its current commit. Pushing a `v*` tag also starts the PyPI release workflow, so use an actual package release to test release documentation.
170
+
171
+ See the [RTD build API](https://docs.readthedocs.com/platform/stable/api/v3.html#build-triggering), [Git integration settings](https://docs.readthedocs.com/platform/stable/reference/git-integration.html), and [GitHub environment settings](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments) for the platform setup details.
172
+
173
+ ## Publishing a new release
174
+
175
+ 1. Update the version in `serpapi/__version__.py`.
176
+ 2. Push a tag for that version. The release pipeline runs automatically:
177
+ ```sh
178
+ git tag v1.2.3
179
+ git push origin v1.2.3
180
+ ```
181
+ This triggers the [release workflow](.github/workflows/release.yml), which tests, builds, and publishes to PyPI, then smoke-tests the published package.
182
+
183
+ > **Required secret:** `API_KEY` (used by the live documentation examples and the published-package smoke test).
@@ -1,6 +1,21 @@
1
1
  Release History
2
2
  ===============
3
3
 
4
+ 1.1.1 (2026-09-08)
5
+ ------------------
6
+
7
+ - Enhancements for SerpApi markdown output (`output=md`) support
8
+ - Enhancements for readthedocs documentation: Added user guide, examples, automated publishing to RTD on release.
9
+
10
+
11
+ 1.1.0 (2026-08-14)
12
+ ------------------
13
+
14
+ - Add PyPI trusted publishing. PYPI Key is no longer required for publishing the package.
15
+ - Add image upload support (`/image` API) for Google Lens
16
+ - Release workflow: Add an option to manually trigger the release workflow and skip live tests
17
+ - Add more test cases: Locations API, pagination, etc.
18
+
4
19
  1.0.1 (2026-03-18)
5
20
  ------------------
6
21
 
@@ -0,0 +1,7 @@
1
+ include README.md CONTRIBUTING.md HISTORY.md LICENSE
2
+ include .readthedocs.yaml
3
+ include scripts/check_docs_revision.py scripts/publish_docs.py
4
+ recursive-include tests *.py
5
+ recursive-include docs *.py *.md *.txt *.css Makefile
6
+ include assets/serpapi-logo.svg assets/serpapi-icon.png
7
+ prune docs/_build
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: serpapi
3
- Version: 1.0.2
3
+ Version: 1.1.1
4
4
  Summary: The official Python client for SerpApi.com.
5
5
  Author-email: SerpApi <support@serpapi.com>
6
6
  License: MIT
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
21
22
  Classifier: Programming Language :: Python :: Implementation :: CPython
22
23
  Classifier: Natural Language :: English
23
24
  Classifier: Topic :: Utilities
@@ -32,6 +33,11 @@ Provides-Extra: color
32
33
  Requires-Dist: pygments; extra == "color"
33
34
  Provides-Extra: test
34
35
  Requires-Dist: pytest; extra == "test"
36
+ Provides-Extra: docs
37
+ Requires-Dist: sphinx<9,>=8.2; python_version >= "3.11" and extra == "docs"
38
+ Requires-Dist: myst-parser<5,>=4; python_version >= "3.11" and extra == "docs"
39
+ Requires-Dist: sphinx-design<1,>=0.6; python_version >= "3.11" and extra == "docs"
40
+ Requires-Dist: sphinx-rtd-theme<4,>=3.1; python_version >= "3.11" and extra == "docs"
35
41
  Dynamic: license-file
36
42
 
37
43
  # SerpApi Python Library & Package
@@ -115,6 +121,22 @@ Documentation is [available on Read the Docs](https://serpapi-python.readthedocs
115
121
 
116
122
  Change history is [available on GitHub](https://github.com/serpapi/serpapi-python/blob/master/HISTORY.md).
117
123
 
124
+ ### Markdown output for AI agents
125
+
126
+ For AI agents and LLM workflows, use `output="md"`. It returns search results with clean headings, links, and tables while using roughly half the tokens of JSON on average.
127
+
128
+ ```python
129
+ markdown = client.search({
130
+ "engine": "google",
131
+ "q": "coffee",
132
+ "output": "md",
133
+ })
134
+ ```
135
+
136
+ Markdown works across SerpApi APIs and is returned as a plain Python string. See [Markdown Output for AI Agents](https://serpapi.com/markdown-output.md) for details.
137
+
138
+ Raw HTML is also available with `output="html"` and is returned as a plain Python string.
139
+
118
140
  ## Basic Examples in Python
119
141
 
120
142
  ### Search Bing
@@ -313,18 +335,36 @@ results = client.search({
313
335
  ```
314
336
  - API Documentation: [serpapi.com/google-reverse-image](https://serpapi.com/google-reverse-image)
315
337
 
316
- ### Search Google Events
338
+ ### Search Google Lens by image URL or upload
339
+
340
+ Google Lens accepts either a publicly accessible image URL or an uploaded
341
+ image. To search by URL, pass the URL directly:
342
+
317
343
  ```python
318
344
  import os
319
345
  import serpapi
320
346
 
321
- client = serpapi.Client(api_key=os.getenv("API_KEY"))
347
+ client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
322
348
  results = client.search({
323
- 'engine': 'google_events',
324
- 'q': 'Events in Austin',
349
+ "engine": "google_lens",
350
+ "url": "https://i.imgur.com/HBrB8p0.png",
325
351
  })
326
352
  ```
327
- - API Documentation: [serpapi.com/google-events-api](https://serpapi.com/google-events-api)
353
+
354
+ To search a local image, place a file named `image.png` in your working directory, upload it, and pass its temporary `image_id` to Google Lens:
355
+
356
+ ```python
357
+ upload = client.upload_image("image.png")
358
+ results = client.search({
359
+ "engine": "google_lens",
360
+ "image_id": upload["image_id"],
361
+ })
362
+ ```
363
+
364
+ Uploaded images can be JPG/JPEG, PNG, or WebP files up to 500 KB. The returned
365
+ `image_id` expires after 10 minutes.
366
+
367
+ - API Documentation: [Google Lens image uploads](https://serpapi.com/google-lens-upload-an-image), [Image API](https://serpapi.com/image-api)
328
368
 
329
369
  ### Search Google Local Services
330
370
  ```python
@@ -404,16 +444,4 @@ MIT License.
404
444
 
405
445
  ## Contributing
406
446
 
407
- Bug reports and pull requests are welcome on GitHub. Once dependencies are installed, you can run the tests with `pytest`.
408
-
409
- ## Publishing a new release
410
-
411
- 1. Update the version in `serpapi/__version__.py`.
412
- 2. Push a tag — the release pipeline runs automatically:
413
- ```sh
414
- git tag v1.2.3
415
- git push origin v1.2.3
416
- ```
417
- This triggers the [release workflow](.github/workflows/release.yml), which tests, builds, and publishes to PyPI, then smoke-tests the published package.
418
-
419
- > **Required secrets:** `PYPI_API_TOKEN` (PyPI upload token) and `API_KEY` (used in smoke-test live search).
447
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, testing, and publishing instructions.
@@ -79,6 +79,22 @@ Documentation is [available on Read the Docs](https://serpapi-python.readthedocs
79
79
 
80
80
  Change history is [available on GitHub](https://github.com/serpapi/serpapi-python/blob/master/HISTORY.md).
81
81
 
82
+ ### Markdown output for AI agents
83
+
84
+ For AI agents and LLM workflows, use `output="md"`. It returns search results with clean headings, links, and tables while using roughly half the tokens of JSON on average.
85
+
86
+ ```python
87
+ markdown = client.search({
88
+ "engine": "google",
89
+ "q": "coffee",
90
+ "output": "md",
91
+ })
92
+ ```
93
+
94
+ Markdown works across SerpApi APIs and is returned as a plain Python string. See [Markdown Output for AI Agents](https://serpapi.com/markdown-output.md) for details.
95
+
96
+ Raw HTML is also available with `output="html"` and is returned as a plain Python string.
97
+
82
98
  ## Basic Examples in Python
83
99
 
84
100
  ### Search Bing
@@ -277,18 +293,36 @@ results = client.search({
277
293
  ```
278
294
  - API Documentation: [serpapi.com/google-reverse-image](https://serpapi.com/google-reverse-image)
279
295
 
280
- ### Search Google Events
296
+ ### Search Google Lens by image URL or upload
297
+
298
+ Google Lens accepts either a publicly accessible image URL or an uploaded
299
+ image. To search by URL, pass the URL directly:
300
+
281
301
  ```python
282
302
  import os
283
303
  import serpapi
284
304
 
285
- client = serpapi.Client(api_key=os.getenv("API_KEY"))
305
+ client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
286
306
  results = client.search({
287
- 'engine': 'google_events',
288
- 'q': 'Events in Austin',
307
+ "engine": "google_lens",
308
+ "url": "https://i.imgur.com/HBrB8p0.png",
289
309
  })
290
310
  ```
291
- - API Documentation: [serpapi.com/google-events-api](https://serpapi.com/google-events-api)
311
+
312
+ To search a local image, place a file named `image.png` in your working directory, upload it, and pass its temporary `image_id` to Google Lens:
313
+
314
+ ```python
315
+ upload = client.upload_image("image.png")
316
+ results = client.search({
317
+ "engine": "google_lens",
318
+ "image_id": upload["image_id"],
319
+ })
320
+ ```
321
+
322
+ Uploaded images can be JPG/JPEG, PNG, or WebP files up to 500 KB. The returned
323
+ `image_id` expires after 10 minutes.
324
+
325
+ - API Documentation: [Google Lens image uploads](https://serpapi.com/google-lens-upload-an-image), [Image API](https://serpapi.com/image-api)
292
326
 
293
327
  ### Search Google Local Services
294
328
  ```python
@@ -368,16 +402,4 @@ MIT License.
368
402
 
369
403
  ## Contributing
370
404
 
371
- Bug reports and pull requests are welcome on GitHub. Once dependencies are installed, you can run the tests with `pytest`.
372
-
373
- ## Publishing a new release
374
-
375
- 1. Update the version in `serpapi/__version__.py`.
376
- 2. Push a tag — the release pipeline runs automatically:
377
- ```sh
378
- git tag v1.2.3
379
- git push origin v1.2.3
380
- ```
381
- This triggers the [release workflow](.github/workflows/release.yml), which tests, builds, and publishes to PyPI, then smoke-tests the published package.
382
-
383
- > **Required secrets:** `PYPI_API_TOKEN` (PyPI upload token) and `API_KEY` (used in smoke-test live search).
405
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, testing, and publishing instructions.
Binary file
@@ -0,0 +1,15 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 96" role="img" aria-label="SerpApi">
2
+ <defs>
3
+ <linearGradient id="serpapi-logo-gradient" x1="12" y1="84" x2="84" y2="12" gradientUnits="userSpaceOnUse">
4
+ <stop offset="0" stop-color="#377FEA"/>
5
+ <stop offset="1" stop-color="#6937EA"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <rect x="0" y="0" width="96" height="96" rx="22" fill="url(#serpapi-logo-gradient)"/>
9
+ <path d="M30 0v31M0 65h30v31M66 31h30M66 31v34M66 65v31" fill="none" stroke="#fff" stroke-width="10" stroke-linecap="round"/>
10
+ <circle cx="30" cy="31" r="12" fill="#fff"/>
11
+ <circle cx="30" cy="65" r="12" fill="#fff"/>
12
+ <circle cx="66" cy="31" r="12" fill="#fff"/>
13
+ <circle cx="66" cy="65" r="12" fill="#fff"/>
14
+ <text x="122" y="62" fill="#ffffff" font-family="Lato, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="43" font-weight="700" letter-spacing="0">SerpApi</text>
15
+ </svg>
@@ -0,0 +1,20 @@
1
+ # Minimal makefile for Sphinx documentation
2
+ #
3
+
4
+ # You can set these variables from the command line, and also
5
+ # from the environment for the first two.
6
+ SPHINXOPTS ?=
7
+ SPHINXBUILD ?= sphinx-build
8
+ SOURCEDIR = .
9
+ BUILDDIR = _build
10
+
11
+ # Put it first so that "make" without argument is like "make help".
12
+ help:
13
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14
+
15
+ .PHONY: help Makefile
16
+
17
+ # Catch-all target: route all unknown targets to Sphinx using the new
18
+ # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19
+ %: Makefile
20
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -0,0 +1,99 @@
1
+ /* Official palette: https://serpapi.com/media */
2
+ :root {
3
+ --serpapi-blue: #377fea;
4
+ --serpapi-purple: #6937ea;
5
+ --serpapi-dark: #313131;
6
+ --serpapi-gradient: linear-gradient(47deg, #377fea, #6937ea);
7
+ --sd-color-primary: var(--serpapi-purple);
8
+ --sd-color-primary-highlight: var(--serpapi-purple);
9
+ --sd-color-primary-text: #ffffff;
10
+ --sd-color-secondary: var(--serpapi-blue);
11
+ --sd-color-tabs-label-active: var(--serpapi-purple);
12
+ --sd-color-tabs-label-hover: var(--serpapi-purple);
13
+ --sd-color-tabs-underline-active: var(--serpapi-blue);
14
+ --sd-color-tabs-underline-hover: var(--serpapi-blue);
15
+ }
16
+
17
+ .wy-side-nav-search > a img.logo {
18
+ width: 210px;
19
+ height: auto;
20
+ }
21
+
22
+ .wy-side-nav-search,
23
+ .wy-nav-top {
24
+ background-color: #2b2145;
25
+ color: #ffffff;
26
+ border-bottom: 4px solid var(--serpapi-blue);
27
+ border-image: var(--serpapi-gradient) 1;
28
+ }
29
+
30
+ .wy-nav-top a {
31
+ color: #ffffff;
32
+ }
33
+
34
+ .wy-side-nav-search input[type="text"] {
35
+ border-color: var(--serpapi-blue);
36
+ }
37
+
38
+ .wy-nav-side {
39
+ background: var(--serpapi-dark);
40
+ }
41
+
42
+ .wy-menu-vertical header,
43
+ .wy-menu-vertical p.caption {
44
+ color: #ffffff;
45
+ height: auto;
46
+ min-height: 32px;
47
+ line-height: 1.5;
48
+ padding-top: 0.4em;
49
+ padding-bottom: 0.4em;
50
+ white-space: normal;
51
+ }
52
+
53
+ .wy-menu-vertical a:hover {
54
+ background-color: var(--serpapi-purple);
55
+ color: #ffffff;
56
+ }
57
+
58
+ .wy-menu-vertical > ul + ul {
59
+ margin-top: 12px;
60
+ }
61
+
62
+ .wy-menu-vertical > ul + ul > li > a {
63
+ font-weight: 700;
64
+ }
65
+
66
+ .wy-menu-vertical li.current > a,
67
+ .wy-menu-vertical li.current > a:hover {
68
+ color: var(--serpapi-purple);
69
+ box-shadow: inset 4px 0 var(--serpapi-blue);
70
+ }
71
+
72
+ .wy-nav-content {
73
+ color: var(--serpapi-dark);
74
+ }
75
+
76
+ /* Purple stays readable for small text on the light content background. */
77
+ .wy-nav-content a:not(.btn),
78
+ .wy-nav-content a:not(.btn):visited,
79
+ .rst-content code.literal,
80
+ .rst-content a code {
81
+ color: var(--serpapi-purple);
82
+ }
83
+
84
+ .wy-nav-content a:not(.btn):hover {
85
+ text-decoration: underline;
86
+ }
87
+
88
+ html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) > dt {
89
+ color: var(--serpapi-purple);
90
+ background: rgba(105, 55, 234, 0.06);
91
+ border-top-color: var(--serpapi-blue);
92
+ }
93
+
94
+ .wy-nav-content a:focus-visible,
95
+ .wy-menu-vertical a:focus-visible,
96
+ .wy-side-nav-search input[type="text"]:focus-visible {
97
+ outline: 2px solid var(--serpapi-blue);
98
+ outline-offset: 2px;
99
+ }
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: "AI Agents"
3
+ description: "Use SerpApi search tools, Markdown results, and API references in AI agents."
4
+ ---
5
+
6
+ # AI Agents
7
+
8
+ An AI agent can call SerpApi to search the web and use the returned text and links when answering a question.
9
+
10
+ ## SerpApi Search Tools
11
+
12
+ If you use a Python agent SDK, we recommend [SerpApi Search Tools](https://github.com/serpapi/serpapi-search-tools-python). It is a separate package for plugging SerpApi search tools into your agents.
13
+
14
+ ## Request Markdown Results
15
+
16
+ To write your own search tool with `serpapi.Client`, pass `output="md"`. Markdown is plain text with formatting for headings, links, and tables.
17
+
18
+ Set your API key as described in [Getting Started](user_guide/getting-started.md#installation), then run:
19
+
20
+ ```python
21
+ import os
22
+ import serpapi
23
+
24
+ client = serpapi.Client(api_key=os.environ["SERPAPI_KEY"])
25
+ markdown = client.search(engine="google", q="Python release news", output="md")
26
+ print(markdown[:500])
27
+ ```
28
+
29
+ The example prints the first 500 characters. Pass the full `markdown` string back to your agent as the search tool's result. See [Output Formats](user_guide/output-formats.md) for JSON, Markdown, and HTML examples and the Python values they return.
30
+
31
+ ## API Parameter Reference
32
+
33
+ Give your coding agent [SerpApi's `llms.txt`](https://serpapi.com/llms.txt) when asking it to write search code. This file lists the Markdown documentation for each API. Ask the agent to read the relevant API page for required parameters, optional filters, and response fields.
@@ -0,0 +1,41 @@
1
+ """Sphinx configuration for local builds and Read the Docs."""
2
+
3
+ import os
4
+
5
+ import serpapi
6
+
7
+ project = "serpapi"
8
+ copyright = "2026 SerpApi, LLC"
9
+ author = "SerpApi, LLC"
10
+ release = serpapi.__version__
11
+ version = release
12
+
13
+ extensions = ["sphinx.ext.autodoc", "myst_parser", "sphinx_design"]
14
+ source_suffix = {".rst": "restructuredtext", ".md": "markdown"}
15
+ root_doc = "index"
16
+ exclude_patterns = ["_build", "build", "Thumbs.db", ".DS_Store"]
17
+ myst_enable_extensions = ["colon_fence"]
18
+ myst_heading_anchors = 3
19
+ autodoc_member_order = "bysource"
20
+ autodoc_default_options = {
21
+ "members": True,
22
+ "imported-members": True,
23
+ "exclude-members": "HTTPClient, from_http_response",
24
+ }
25
+
26
+ html_theme = "sphinx_rtd_theme"
27
+ html_static_path = ["_static"]
28
+ html_css_files = ["custom.css"]
29
+ html_logo = "../assets/serpapi-logo.svg"
30
+ html_favicon = "../assets/serpapi-icon.png"
31
+ html_theme_options = {
32
+ "logo_only": True,
33
+ "style_nav_header_background": "#2b2145",
34
+ "collapse_navigation": False,
35
+ "sticky_navigation": True,
36
+ "navigation_depth": 3,
37
+ "titles_only": True,
38
+ }
39
+ html_baseurl = os.environ.get(
40
+ "READTHEDOCS_CANONICAL_URL", "https://serpapi-python.readthedocs.io/en/latest/"
41
+ )