https://github.com/irahorecka/comics
GoComics API wrapper
https://github.com/irahorecka/comics
api comic-strips comics comics-downloader gocomics
Last synced: 4 months ago
JSON representation
GoComics API wrapper
- Host: GitHub
- URL: https://github.com/irahorecka/comics
- Owner: irahorecka
- License: mit
- Created: 2022-10-04T01:05:58.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-06-12T20:09:23.000Z (about 1 year ago)
- Last Synced: 2025-09-24T18:56:55.467Z (9 months ago)
- Topics: api, comic-strips, comics, comics-downloader, gocomics
- Language: Python
- Homepage:
- Size: 439 KB
- Stars: 28
- Watchers: 6
- Forks: 5
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# comics
[GoComics](https://www.gocomics.com/) API wrapper
[](https://www.python.org/downloads/)
[](https://pypi.python.org/pypi/comics)
[](https://raw.githubusercontent.com/irahorecka/comics/main/LICENSE)
[](https://github.com/irahorecka/comics/actions)
## Installation
```bash
pip install comics
```
> [!WARNING]
> **Breaking changes since v0.9.1**
> Versions prior to v0.9.1 are incompatible due to an upstream change. Upgrading to the latest release is required.
> ```
> pip install comics --upgrade
> ```
> [!NOTE]
> Playwright must be installed after installing `comics` to enable browser-based features:
> ```
> python -m playwright install --with-deps
> ```
## Quick start
Find and download the Calvin and Hobbes comic strip published on January 2, 1990:
```python
import comics
ch = comics.search("calvinandhobbes", date="1990-01-02")
ch.download("calvinandhobbes.png")
```
## Find comics
Available comics can be found using the `directory` class:
```python
import comics
# List available comics - total of 401
comics.directory.listall()
# >>> ("1-and-done", "9-chickweed-lane-classics", "9chickweedlane", "9to5", ... )
# Find endpoints for Calvin and Hobbes
comics.directory.search("Calvin and Hobbes")
# >>> ("calvinandhobbes", "calvinandhobbesenespanol")
```
First, pass the desired endpoint to `comics.search`. For example, to search for Calvin and Hobbes comics in english use `comics.search("calvinandhobbes")`; for spanish, use `comics.search("calvinandhobbesenespanol")`.
## Search and download comics
Then, search for a comic strip by passing `date` into `search()`:
```python
import comics
# Get a Calvin and Hobbes comic strip by date
ch = comics.search("calvinandhobbes", date="2013-05-13") # Also accepts datetime.date or datetime object
# Get a random Calvin and Hobbes comic strip
random_ch = comics.search("calvinandhobbes", date="random")
```
Finally, show, download, or stream the comic strip:
```python
# Show comic strip - opens in Jupyter notebook or default image viewer application
ch.show()
# Download comic strip - defaults to {endpoint}.png if an export path is not provided
# E.g., a Calvin and Hobbes comic strip will be exported as "calvinandhobbes.png" in the current working directory
ch.download()
# Stream comic strip - useful if custom image content manipulation is desired
ch.stream()
```
### Retry logic
If a comic strip fails to load due to CDN delays or missing image data, a retry mechanism is built into `download()`, `show()`, and `stream()`. You can control this behavior via:
- `retries`: number of attempts before failing (default = 5)
- `base_delay`: exponential backoff seed time in seconds (default = 0.5)
This improves reliability when fetching newly released strips or handling transient issues.
| Attempt | Wait Before Attempt (sec) | Cumulative Time (sec) |
|---------|---------------------------|------------------------|
| 1 | 0.0 | 0.0 |
| 2 | 0.5 | 0.5 |
| 3 | 1.0 | 1.5 |
| 4 | 2.0 | 3.5 |
| 5 | 4.0 | 7.5 |
| 6 | 8.0 | 15.5 |
Retry behavior can be customized per call:
```python
# Try 3 times total with shorter delay
ch.download(retries=2, base_delay=0.25)
```
## Attributes
An instantiated `search` class will have the following public attributes:
```python
import comics
garfield = comics.search("garfield")
garfield.endpoint
# >>> "garfield"
garfield.title
# >>> "Garfield"
garfield.start_date
# >>> "1978-06-19"
```
An instantiated `search` class with `date` will have the following public attributes:
```python
import comics
garfield = comics.search("garfield", date="2000-08-20")
garfield.endpoint
# >>> "garfield"
garfield.title
# >>> "Garfield"
garfield.date
# >>> "2000-08-20"
garfield.url
# >>> "https://www.gocomics.com/garfield/2000/08/20"
garfield.image_url
# >>> "https://assets.amuniversal.com/6694c52099bd01365606005056a9545d"
```
## Exceptions
An exception will be thrown if the queried date is unregistered or before the comic's origin date:
```python
import comics
try:
peanuts = comics.search("peanuts", date="1900-01-01")
peanuts.download()
except comics.exceptions.InvalidDateError:
print("Whoops, an invalid date was queried.")
```
An exception will be thrown if the queried endpoint is unregistered:
```python
import comics
try:
invalid_comic = comics.search("invalid_endpoint", date="2000-01-01")
invalid_comic.download()
except comics.exceptions.InvalidEndpointError:
print("Whoops, an invalid endpoint was queried.")
```
An exception will be thrown if Playwright fails to fetch a comic (e.g., browser not installed or page error):
```python
import comics
try:
garfield = comics.search("garfield", date="2020-05-05", force_playwright=True)
garfield.download()
except comics.exceptions.ComicsPlaywrightError:
print("Playwright failed to fetch the page. Check your Playwright installation.")
```
## Contribute
- [Issues Tracker](https://github.com/irahorecka/comics/issues)
- [Source Code](https://github.com/irahorecka/comics/tree/main/comics)
## Support
If you are having issues or would like to propose a new feature, please use the [issues tracker](https://github.com/irahorecka/comics/issues).
## License
This project is licensed under the MIT license.