# Python SDK for ngrok
[![PyPI][pypi-badge]][pypi-url]
[![Supported Versions][ver-badge]][ver-url]
[![MIT licensed][mit-badge]][mit-url]
[![Apache-2.0 licensed][apache-badge]][apache-url]
[![Continuous integration][ci-badge]][ci-url]
[pypi-badge]: https://img.shields.io/pypi/v/ngrok
[pypi-url]: https://pypi.org/project/ngrok
[ver-badge]: https://img.shields.io/pypi/pyversions/ngrok.svg
[ver-url]: https://pypi.org/project/ngrok
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
[mit-url]: https://github.com/ngrok/ngrok-rust/blob/main/LICENSE-MIT
[apache-badge]: https://img.shields.io/badge/license-Apache_2.0-blue.svg
[apache-url]: https://github.com/ngrok/ngrok-rust/blob/main/LICENSE-APACHE
[ci-badge]: https://github.com/ngrok/ngrok-python/actions/workflows/ci.yml/badge.svg
[ci-url]: https://github.com/ngrok/ngrok-python/actions/workflows/ci.yml
`ngrok-python` is the official Python SDK for ngrok that requires no binaries. Quickly enable secure production-ready connectivity to your applications and services directly from your code.
[ngrok](https://ngrok.com) is a globally distributed gateway that provides secure connectivity for applications and services running in any environment.
# Installation
The `ngrok-python` SDK can be installed from [PyPI](https://pypi.org/project/ngrok) via `pip`:
```shell
pip install ngrok
```
# Quickstart
1. [Install `ngrok-python`](#installation)
2. Export your [authtoken from the ngrok dashboard](https://dashboard.ngrok.com/get-started/your-authtoken) as `NGROK_AUTHTOKEN` in your terminal
3. Add the following code to your application to establish connectivity via the [forward method](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-forward-minimal.py) through port `9000` on `localhost`:
```python
# import ngrok python sdk
import ngrok
import time
# Establish connectivity
listener = ngrok.forward(9000, authtoken_from_env=True)
# Output ngrok url to console
print(f"Ingress established at {listener.url()}")
# Keep the listener alive
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Closing listener")
```
That's it! Your application should now be available through the url output in your terminal.
> **Note**
> You can find more examples in [the examples directory](https://github.com/ngrok/ngrok-python/tree/main/examples).
# Documentation
A full quickstart guide and API reference can be found in the [ngrok-python documentation](https://ngrok.github.io/ngrok-python/).
### Authentication
To use most of ngrok's features, you'll need an authtoken. To obtain one, sign up for free at [ngrok.com](https://dashboard.ngrok.com/signup) and retrieve it from the [authtoken page in your ngrok dashboard](https://dashboard.ngrok.com/get-started/your-authtoken). Once you have copied your authtoken, you can reference it in several ways.
You can set it in the `NGROK_AUTHTOKEN` environment variable and pass `authtoken_from_env=True` to the [forward](https://ngrok.github.io/ngrok-python/module.html) method:
```python
ngrok.forward(authtoken_from_env=True, ...)
```
Or pass the authtoken directly to the [forward](https://ngrok.github.io/ngrok-python/module.html) method:
```python
ngrok.forward(authtoken=token, ...)
```
Or set it for all connections with the [set_auth_token](https://ngrok.github.io/ngrok-python/module.html) method:
```python
ngrok.set_auth_token(token)
```
### Connection
The [forward](https://ngrok.github.io/ngrok-python/module.html) method is the easiest way to start an ngrok session and establish a listener to a specified address. If an asynchronous runtime is running, the [forward](https://ngrok.github.io/ngrok-python/module.html) method returns a promise that resolves to the public listener object.
With no arguments, the [forward](https://ngrok.github.io/ngrok-python/module.html) method will start an HTTP listener to `localhost` port `80`:
```python
listener = ngrok.forward()
```
You can pass the port number to forward on `localhost`:
```python
listener = ngrok.forward(4242)
```
Or you can specify the host and port via a string:
```python
listener = ngrok.forward("localhost:4242")
```
More options can be passed to the `forward` method to customize the connection:
```python
listener = ngrok.forward(8080, basic_auth="ngrok:online1line"})
listener = ngrok.forward(8080, oauth_provider="google", oauth_allow_domains="example.com")
```
The second (optional) argument is the listener type, which defaults to `http`. To create a TCP listener:
```python
listener = ngrok.forward(25565, "tcp")
```
Since the options are kwargs, you can also use the `**` operator to pass a dictionary for configuration:
```python
options = {"authtoken_from_env":True, "response_header_add":"X-Awesome:yes"}
listener = ngrok.forward(8080, **options)
```
See [Full Configuration](#full-configuration) for the list of possible configuration options.
### Disconnection
To close a listener use the [disconnect](https://ngrok.github.io/ngrok-python/module.html) method with the `url` of the listener to close. If there is an asynchronous runtime running the [disconnect](https://ngrok.github.io/ngrok-python/module.html) method returns a promise that resolves when the call is complete.
```python
ngrok.disconnect(url)
```
Or omit the `url` to close all listeners:
```python
ngrok.disconnect()
```
The [close](https://ngrok.github.io/ngrok-python/ngrok_listener.html) method on a listener will shut it down, and also stop the ngrok session if it is no longer needed. This method returns a promise that resolves when the listener is closed.
```python
await listener.close()
```
### List all Listeners
To list all current non-closed listeners use the [get_listeners](https://ngrok.github.io/ngrok-python/module.html) method. If there is an asynchronous runtime running the [get_listeners](https://ngrok.github.io/ngrok-python/module.html) method returns a promise that resolves to the list of listener objects.
```python
listeners = ngrok.get_listeners()
```
### TLS Backends
As of version `0.10.0` there is backend TLS connection support, validated by a filepath specified in the `SSL_CERT_FILE` environment variable, or falling back to the host OS installed trusted certificate authorities. So it is now possible to do this to connect:
```python
ngrok.forward("https://127.0.0.1:3000", authtoken_from_env=True)
```
If the service is using certs not trusted by the OS, such as self-signed certificates, add an environment variable like this before running: `SSL_CERT_FILE=/path/to/ca.crt`. There is also a `verify_upstream_tls=False` option to disable certification verification.
### Unix Sockets
You may also choose to use Unix Sockets instead of TCP. You can view an example of this [here](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-http-full.py).
A socket address may be passed directly into the listener `forward()` call as well by prefixing the address with `unix:`, for example `unix:/tmp/socket-123`.
### Builders
For more control over Sessions and Listeners, the builder classes can be used.
A minimal example using the builder class looks like [the following](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-http-minimal.py):
```python
async def create_listener():
session = await ngrok.NgrokSessionBuilder().authtoken_from_env().connect()
listener = await session.http_endpoint().listen()
print (f"Ingress established at {listener.url()}")
listener.forward("localhost:9000")
```
See here for a [Full Configuration Example](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-http-full.py)
### Full Configuration
This example shows [all the possible configuration items of ngrok.forward](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-forward-full.py):
```python
listener = ngrok.forward(
# session configuration
addr="localhost:8080",
authtoken="<authtoken>",
authtoken_from_env=True,
app_protocol="http2",
session_metadata="Online in One Line",
# advanced session connection configuration
server_addr="example.com:443",
root_cas="trusted",
session_ca_cert=load_file("ca.pem"),
# listener configuration
metadata="example listener metadata from python",
domain="<domain>",
schemes=["HTTPS"],
proto="http",
proxy_proto="", # One of: "", "1", "2"
labels="edge:edghts_2G...", # Along with proto="labeled"
# module configuration
basic_auth=["ngrok:online1line"],
circuit_breaker=0.1,
compression=True,
allow_user_agent="^mozilla.*",
deny_user_agent="^curl.*",
allow_cidr="0.0.0.0/0",
deny_cidr="10.1.1.1/32",
crt=load_file("crt.pem"),
key=load_file("key.pem"),
mutual_tls_cas=load_file("ca.crt"),
oauth_provider="google",
oauth_allow_domains=["<domain>"],
oauth_allow_emails=["<email>"],
oauth_scopes=["<scope>"],
oauth_client_id="<id>",
oauth_client_secret="<id>",
oidc_issuer_url="<url>",
oidc_client_id="<id>",
oidc_client_secret="<secret>",
oidc_allow_domains=["<domain>"],
oidc_allow_emails=["<email>"],
oidc_scopes=["<scope>"],
policy="<policy_json>",
request_header_remove="X-Req-Nope",
response_header_remove="X-Res-Nope",
request_header_add="X-Req-Yup:true",
response_header_add="X-Res-Yup:true",
verify_upstream_tls=False,
verify_webhook_provider="twilio",
verify_webhook_secret="asdf",
websocket_tcp_converter=True,
)
```
# ASGI Runner
`ngrok-python` comes bundled with an ASGI (Asynchronous Server Gateway Interface) runner `ngrok-asgi` that can be used for Uvicorn, Gunicorn, Django and more, with no code.
To use prefix your start up command for a Uvicorn or Gunicorn web server with either `ngrok-asgi` or `python -m ngrok`.
Any TCP or Unix Domain Socket arguments will be used to establish connectivity automatically. The ngrok listener can be configured using command flags, for instance adding `--basic-auth ngrok online1line` will introduce basic authentication to the ingress listener.
### Uvicorn
```shell
# Basic Usage
ngrok-asgi uvicorn mysite.asgi:application
# With custom host and port
ngrok-asgi uvicorn mysite.asgi:application \
--host localhost \
--port 1234
# Using basic auth
ngrok-asgi uvicorn mysite.asgi:application \
--host localhost \
--port 1234 \
--basic-auth ngrok online1line
# Using custom sock file
ngrok-asgi uvicorn mysite.asgi:application \
--uds /tmp/uvicorn.sock
# Using module name
python -m ngrok uvicorn mysite.asgi:application \
--oauth-provider google \
--allow-emails bob@example.com
```
### Gunicorn
```shell
# Basic Usage
ngrok-asgi gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker
# With custom host and port
ngrok-asgi gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker \
--bind localhost:1234
# Using webhook verifications
ngrok-asgi gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker \
--webhook-verification twilio s3cr3t
# Using custom sock file
ngrok-asgi gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker \
--bind unix:/tmp/gunicorn.sock
# Using module name
python -m ngrok gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker --response-header X-Awesome True
```
# Examples
#### Listeners
- [HTTP](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-http-minimal.py)
- [Full Configuration Example](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-http-full.py)
- [Labeled](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-labeled.py)
- [TCP](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-tcp.py)
- [TLS](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-tls.py)
#### Frameworks
- [AIOHTTP](https://github.com/ngrok/ngrok-python/tree/main/examples/aiohttp-ngrok.py)
- [AWS APP Runner](https://github.com/ngrok/ngrok-sdk-serverless-example)
- with [changes for Python](https://docs.aws.amazon.com/apprunner/latest/dg/service-source-code-python.html)
- Django
- [Single File Example](https://github.com/ngrok/ngrok-python/tree/main/examples/django-single-file.py)
- [Modify manage.py Example](https://github.com/ngrok/ngrok-python/tree/main/examples/djangosite/manage.py)
- [Modify asgi.py Example](https://github.com/ngrok/ngrok-python/tree/main/examples/djangosite/djangosite/ngrok-asgi.py)
- or [via `ngrok-asgi`](#asgi-runner)
- [Flask](https://github.com/ngrok/ngrok-python/tree/main/examples/flask-ngrok.py)
- [Gunicorn](#gunicorn)
- [Hypercorn](https://github.com/ngrok/ngrok-python/tree/main/examples/hypercorn-http2-ngrok.py)
- [Streamlit](https://github.com/ngrok/ngrok-python/tree/main/examples/streamlit/streamlit-ngrok.py)
- [Tornado](https://github.com/ngrok/ngrok-python/tree/main/examples/tornado-ngrok.py)
- [Uvicorn](https://github.com/ngrok/ngrok-python/tree/main/examples/uvicorn-ngrok.py)
#### Machine Learning
- Gradio
- [ngrok-asgi Example](https://github.com/ngrok/ngrok-python/tree/main/examples/gradio/gradio-asgi.py)
- [gradio CLI Example](https://github.com/ngrok/ngrok-python/tree/main/examples/gradio/gradio-ngrok.py)
- [OpenPlayground](https://github.com/ngrok/ngrok-python/tree/main/examples/openplayground/run.py)
- [GPT4ALL](https://github.com/ngrok/ngrok-python/tree/main/examples/gpt4all/run.py)
- [Stable Diffusion WebUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui/) by AUTOMATIC1111
- `ngrok-python` is now built-in, see the `--ngrok` and `--ngrok-options` arguments.
- [Text Generation WebUI](https://github.com/oobabooga/text-generation-webui) by oobabooga
- `ngrok-python` is now built-in, see the `--extension ngrok` argument.
# Platform Support
Pre-built binaries are provided on PyPI for the following platforms:
| OS | i686 | x64 | aarch64 | arm |
| ---------- | -----|-----|---------|-----|
| Windows | ✓ | ✓ | * | |
| MacOS | | ✓ | ✓ | |
| Linux | | ✓ | ✓ | ✓ |
| Linux musl | | ✓ | ✓ | |
| FreeBSD | | * | | |
> **Note**
> `ngrok-python`, and [ngrok-rust](https://github.com/ngrok/ngrok-rust/) which it depends on, are open source, so it may be possible to build them for other platforms.
> - Windows-aarch64 will be supported after the next release of [Ring](https://github.com/briansmith/ring/issues/1167).
> - FreeBSD-x64 is built by the release process, but PyPI won't accept BSD flavors.
# Dependencies
- This project relies on [PyO3](https://pyo3.rs/), an excellent system to ease development and building of Rust plugins for Python.
- Thank you to [OpenIoTHub](https://github.com/OpenIoTHub/ngrok) for handing over the ngrok name on PyPI.
# Changelog
Changes to `ngrok-python` are tracked under [CHANGELOG.md](https://github.com/ngrok/ngrok-python/blob/main/CHANGELOG.md).
# Join the ngrok Community
- Check out [our official docs](https://docs.ngrok.com)
- Read about updates on [our blog](https://blog.ngrok.com)
- Open an [issue](https://github.com/ngrok/ngrok-python/issues) or [pull request](https://github.com/ngrok/ngrok-python/pulls)
- Join our [Slack community](https://ngrok.com/slack)
- Follow us on [X / Twitter (@ngrokHQ)](https://twitter.com/ngrokhq)
- Subscribe to our [Youtube channel (@ngrokHQ)](https://www.youtube.com/@ngrokhq)
# License
This project is dual-licensed under [Apache, Version 2.0](LICENSE-APACHE) and [MIT](LICENSE-MIT).
You can choose between one of them if you use this work.
### Contributions
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in `ngrok-python` by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
# Development: Getting Started
**Prerequisites:**
- a valid Ngrok `authtoken`
- `make` available in your PATH
1. Update [Cargo.toml](./Cargo.toml) with the _latest supported_ ```ngrok = { version = "=VERSION_HERE" }``` from [ngrok-rust](https://github.com/ngrok/ngrok-rust/blob/main/ngrok/Cargo.toml#L3). `ngrok-rust` is used for the bindings in [src/rust_files_here.rs](./src)
2. Run `make build` (builds the `rust` bindings / `python` dependencies)
3. Happy developing!
<br/>
**Example Commands**:
_building the project_
```shell
make develop
```
_running the entire test suite_
```shell
# running the entire test suite
export NGROK_AUTHTOKEN="YOUR_AUTHTOKEN_HERE"; make test
```
_running an individual test_
```shell
# running an individual test
export NGROK_AUTHTOKEN="YOUR_AUTHTOKEN_HERE"; make test="-k TEST_CLASS.NAME_OF_TEST" test
```
[See the MakeFile for more examples](./Makefile)
### HTTP2
The examples include a minimal `hypercorn` HTTP/2 example if you run `make http2`. You can curl the endpoint logged with `INFO:ngrok.listener:Created` and verify the HTTP/2 response from `hypercorn`.
```bash
curl --http2 -v https://<YOUR_LISTENER_URL>
* Trying <YOUR_IP>:443...
* Connected to a6278d6c07ce.ngrok.app (<YOUR_IP>) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
...
> GET / HTTP/2
> Host: a6278d6c07ce.ngrok.app
> user-agent: curl/7.81.0
> accept: */*
>
...
< HTTP/2 200
< content-type: text/plain
< date: Fri, 01 Mar 2024 18:50:23 GMT
< ngrok-agent-ips: <YOUR_AGENT_IP>
< ngrok-trace-id: ed038ace04876818149cf0769bd43e38
< server: hypercorn-h2
<
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection #0 to host <YOUR_LISTENER_URL> left intact
hello
```
Raw data
{
"_id": null,
"home_page": null,
"name": "ngrok",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "ngrok, python, pypi, pyo3, ingress, networking",
"author": null,
"author_email": null,
"download_url": null,
"platform": null,
"description": "# Python SDK for ngrok\n\n[![PyPI][pypi-badge]][pypi-url]\n[![Supported Versions][ver-badge]][ver-url]\n[![MIT licensed][mit-badge]][mit-url]\n[![Apache-2.0 licensed][apache-badge]][apache-url]\n[![Continuous integration][ci-badge]][ci-url]\n\n[pypi-badge]: https://img.shields.io/pypi/v/ngrok\n[pypi-url]: https://pypi.org/project/ngrok\n[ver-badge]: https://img.shields.io/pypi/pyversions/ngrok.svg\n[ver-url]: https://pypi.org/project/ngrok\n[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg\n[mit-url]: https://github.com/ngrok/ngrok-rust/blob/main/LICENSE-MIT\n[apache-badge]: https://img.shields.io/badge/license-Apache_2.0-blue.svg\n[apache-url]: https://github.com/ngrok/ngrok-rust/blob/main/LICENSE-APACHE\n[ci-badge]: https://github.com/ngrok/ngrok-python/actions/workflows/ci.yml/badge.svg\n[ci-url]: https://github.com/ngrok/ngrok-python/actions/workflows/ci.yml\n\n`ngrok-python` is the official Python SDK for ngrok that requires no binaries. Quickly enable secure production-ready connectivity to your applications and services directly from your code.\n\n[ngrok](https://ngrok.com) is a globally distributed gateway that provides secure connectivity for applications and services running in any environment.\n\n# Installation\n\nThe `ngrok-python` SDK can be installed from [PyPI](https://pypi.org/project/ngrok) via `pip`:\n\n```shell\npip install ngrok\n```\n\n# Quickstart\n\n1. [Install `ngrok-python`](#installation)\n2. Export your [authtoken from the ngrok dashboard](https://dashboard.ngrok.com/get-started/your-authtoken) as `NGROK_AUTHTOKEN` in your terminal\n3. Add the following code to your application to establish connectivity via the [forward method](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-forward-minimal.py) through port `9000` on `localhost`:\n\n ```python\n # import ngrok python sdk\n import ngrok\n import time\n \n # Establish connectivity\n listener = ngrok.forward(9000, authtoken_from_env=True)\n \n # Output ngrok url to console\n print(f\"Ingress established at {listener.url()}\")\n\n # Keep the listener alive\n try:\n while True:\n time.sleep(1)\n except KeyboardInterrupt:\n print(\"Closing listener\")\n ```\n\nThat's it! Your application should now be available through the url output in your terminal. \n\n> **Note**\n> You can find more examples in [the examples directory](https://github.com/ngrok/ngrok-python/tree/main/examples).\n\n# Documentation\n\nA full quickstart guide and API reference can be found in the [ngrok-python documentation](https://ngrok.github.io/ngrok-python/).\n\n### Authentication\n\nTo use most of ngrok's features, you'll need an authtoken. To obtain one, sign up for free at [ngrok.com](https://dashboard.ngrok.com/signup) and retrieve it from the [authtoken page in your ngrok dashboard](https://dashboard.ngrok.com/get-started/your-authtoken). Once you have copied your authtoken, you can reference it in several ways.\n\nYou can set it in the `NGROK_AUTHTOKEN` environment variable and pass `authtoken_from_env=True` to the [forward](https://ngrok.github.io/ngrok-python/module.html) method:\n\n```python\nngrok.forward(authtoken_from_env=True, ...)\n```\n\nOr pass the authtoken directly to the [forward](https://ngrok.github.io/ngrok-python/module.html) method:\n\n```python\nngrok.forward(authtoken=token, ...)\n```\n\nOr set it for all connections with the [set_auth_token](https://ngrok.github.io/ngrok-python/module.html) method:\n\n```python\nngrok.set_auth_token(token)\n```\n\n### Connection\n\nThe [forward](https://ngrok.github.io/ngrok-python/module.html) method is the easiest way to start an ngrok session and establish a listener to a specified address. If an asynchronous runtime is running, the [forward](https://ngrok.github.io/ngrok-python/module.html) method returns a promise that resolves to the public listener object.\n\nWith no arguments, the [forward](https://ngrok.github.io/ngrok-python/module.html) method will start an HTTP listener to `localhost` port `80`:\n\n```python\nlistener = ngrok.forward()\n```\n\nYou can pass the port number to forward on `localhost`:\n\n```python\nlistener = ngrok.forward(4242)\n```\n\nOr you can specify the host and port via a string:\n\n```python\nlistener = ngrok.forward(\"localhost:4242\")\n```\n\nMore options can be passed to the `forward` method to customize the connection:\n\n```python\nlistener = ngrok.forward(8080, basic_auth=\"ngrok:online1line\"})\nlistener = ngrok.forward(8080, oauth_provider=\"google\", oauth_allow_domains=\"example.com\")\n```\n\nThe second (optional) argument is the listener type, which defaults to `http`. To create a TCP listener:\n\n```python\nlistener = ngrok.forward(25565, \"tcp\")\n```\n\nSince the options are kwargs, you can also use the `**` operator to pass a dictionary for configuration:\n\n```python\noptions = {\"authtoken_from_env\":True, \"response_header_add\":\"X-Awesome:yes\"}\nlistener = ngrok.forward(8080, **options)\n```\n\nSee [Full Configuration](#full-configuration) for the list of possible configuration options.\n\n### Disconnection\n\nTo close a listener use the [disconnect](https://ngrok.github.io/ngrok-python/module.html) method with the `url` of the listener to close. If there is an asynchronous runtime running the [disconnect](https://ngrok.github.io/ngrok-python/module.html) method returns a promise that resolves when the call is complete.\n\n```python\nngrok.disconnect(url)\n```\n\nOr omit the `url` to close all listeners:\n\n```python\nngrok.disconnect()\n```\n\nThe [close](https://ngrok.github.io/ngrok-python/ngrok_listener.html) method on a listener will shut it down, and also stop the ngrok session if it is no longer needed. This method returns a promise that resolves when the listener is closed.\n\n```python\nawait listener.close()\n```\n\n### List all Listeners\n\nTo list all current non-closed listeners use the [get_listeners](https://ngrok.github.io/ngrok-python/module.html) method. If there is an asynchronous runtime running the [get_listeners](https://ngrok.github.io/ngrok-python/module.html) method returns a promise that resolves to the list of listener objects.\n\n```python\nlisteners = ngrok.get_listeners()\n```\n\n### TLS Backends\n\nAs of version `0.10.0` there is backend TLS connection support, validated by a filepath specified in the `SSL_CERT_FILE` environment variable, or falling back to the host OS installed trusted certificate authorities. So it is now possible to do this to connect:\n\n```python\nngrok.forward(\"https://127.0.0.1:3000\", authtoken_from_env=True)\n```\n\nIf the service is using certs not trusted by the OS, such as self-signed certificates, add an environment variable like this before running: `SSL_CERT_FILE=/path/to/ca.crt`. There is also a `verify_upstream_tls=False` option to disable certification verification.\n\n### Unix Sockets\n\nYou may also choose to use Unix Sockets instead of TCP. You can view an example of this [here](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-http-full.py).\n\nA socket address may be passed directly into the listener `forward()` call as well by prefixing the address with `unix:`, for example `unix:/tmp/socket-123`.\n\n### Builders\n\nFor more control over Sessions and Listeners, the builder classes can be used.\n\nA minimal example using the builder class looks like [the following](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-http-minimal.py):\n\n```python\nasync def create_listener():\n session = await ngrok.NgrokSessionBuilder().authtoken_from_env().connect()\n listener = await session.http_endpoint().listen()\n print (f\"Ingress established at {listener.url()}\")\n listener.forward(\"localhost:9000\")\n```\n\nSee here for a [Full Configuration Example](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-http-full.py)\n\n### Full Configuration\n\nThis example shows [all the possible configuration items of ngrok.forward](https://github.com/ngrok/ngrok-python/blob/main/examples/ngrok-forward-full.py):\n\n```python\nlistener = ngrok.forward(\n # session configuration\n addr=\"localhost:8080\",\n authtoken=\"<authtoken>\",\n authtoken_from_env=True,\n app_protocol=\"http2\",\n session_metadata=\"Online in One Line\",\n # advanced session connection configuration\n server_addr=\"example.com:443\",\n root_cas=\"trusted\",\n session_ca_cert=load_file(\"ca.pem\"),\n # listener configuration\n metadata=\"example listener metadata from python\",\n domain=\"<domain>\",\n schemes=[\"HTTPS\"],\n proto=\"http\",\n proxy_proto=\"\", # One of: \"\", \"1\", \"2\"\n labels=\"edge:edghts_2G...\", # Along with proto=\"labeled\"\n # module configuration\n basic_auth=[\"ngrok:online1line\"],\n circuit_breaker=0.1,\n compression=True,\n allow_user_agent=\"^mozilla.*\",\n deny_user_agent=\"^curl.*\",\n allow_cidr=\"0.0.0.0/0\",\n deny_cidr=\"10.1.1.1/32\",\n crt=load_file(\"crt.pem\"),\n key=load_file(\"key.pem\"),\n mutual_tls_cas=load_file(\"ca.crt\"),\n oauth_provider=\"google\",\n oauth_allow_domains=[\"<domain>\"],\n oauth_allow_emails=[\"<email>\"],\n oauth_scopes=[\"<scope>\"],\n oauth_client_id=\"<id>\",\n oauth_client_secret=\"<id>\",\n oidc_issuer_url=\"<url>\",\n oidc_client_id=\"<id>\",\n oidc_client_secret=\"<secret>\",\n oidc_allow_domains=[\"<domain>\"],\n oidc_allow_emails=[\"<email>\"],\n oidc_scopes=[\"<scope>\"],\n policy=\"<policy_json>\",\n request_header_remove=\"X-Req-Nope\",\n response_header_remove=\"X-Res-Nope\",\n request_header_add=\"X-Req-Yup:true\",\n response_header_add=\"X-Res-Yup:true\",\n verify_upstream_tls=False,\n verify_webhook_provider=\"twilio\",\n verify_webhook_secret=\"asdf\",\n websocket_tcp_converter=True,\n)\n```\n\n# ASGI Runner\n\n`ngrok-python` comes bundled with an ASGI (Asynchronous Server Gateway Interface) runner `ngrok-asgi` that can be used for Uvicorn, Gunicorn, Django and more, with no code. \n\nTo use prefix your start up command for a Uvicorn or Gunicorn web server with either `ngrok-asgi` or `python -m ngrok`. \n\nAny TCP or Unix Domain Socket arguments will be used to establish connectivity automatically. The ngrok listener can be configured using command flags, for instance adding `--basic-auth ngrok online1line` will introduce basic authentication to the ingress listener.\n\n### Uvicorn\n\n```shell\n# Basic Usage\nngrok-asgi uvicorn mysite.asgi:application\n\n# With custom host and port\nngrok-asgi uvicorn mysite.asgi:application \\\n --host localhost \\\n --port 1234\n\n# Using basic auth\nngrok-asgi uvicorn mysite.asgi:application \\\n --host localhost \\\n --port 1234 \\\n --basic-auth ngrok online1line\n\n# Using custom sock file\nngrok-asgi uvicorn mysite.asgi:application \\\n --uds /tmp/uvicorn.sock\n\n# Using module name\npython -m ngrok uvicorn mysite.asgi:application \\\n --oauth-provider google \\\n --allow-emails bob@example.com\n```\n\n### Gunicorn\n\n```shell\n# Basic Usage\nngrok-asgi gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker\n\n# With custom host and port\nngrok-asgi gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker \\\n --bind localhost:1234\n\n# Using webhook verifications\nngrok-asgi gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker \\\n --webhook-verification twilio s3cr3t\n\n# Using custom sock file\nngrok-asgi gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker \\\n --bind unix:/tmp/gunicorn.sock\n\n# Using module name\npython -m ngrok gunicorn mysite.asgi:application -k uvicorn.workers.UvicornWorker --response-header X-Awesome True\n```\n\n# Examples\n\n#### Listeners\n - [HTTP](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-http-minimal.py)\n - [Full Configuration Example](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-http-full.py)\n - [Labeled](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-labeled.py)\n - [TCP](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-tcp.py)\n - [TLS](https://github.com/ngrok/ngrok-python/tree/main/examples/ngrok-tls.py)\n\n#### Frameworks\n - [AIOHTTP](https://github.com/ngrok/ngrok-python/tree/main/examples/aiohttp-ngrok.py)\n - [AWS APP Runner](https://github.com/ngrok/ngrok-sdk-serverless-example)\n - with [changes for Python](https://docs.aws.amazon.com/apprunner/latest/dg/service-source-code-python.html)\n - Django\n - [Single File Example](https://github.com/ngrok/ngrok-python/tree/main/examples/django-single-file.py)\n - [Modify manage.py Example](https://github.com/ngrok/ngrok-python/tree/main/examples/djangosite/manage.py)\n - [Modify asgi.py Example](https://github.com/ngrok/ngrok-python/tree/main/examples/djangosite/djangosite/ngrok-asgi.py)\n - or [via `ngrok-asgi`](#asgi-runner)\n - [Flask](https://github.com/ngrok/ngrok-python/tree/main/examples/flask-ngrok.py)\n - [Gunicorn](#gunicorn)\n - [Hypercorn](https://github.com/ngrok/ngrok-python/tree/main/examples/hypercorn-http2-ngrok.py)\n - [Streamlit](https://github.com/ngrok/ngrok-python/tree/main/examples/streamlit/streamlit-ngrok.py)\n - [Tornado](https://github.com/ngrok/ngrok-python/tree/main/examples/tornado-ngrok.py)\n - [Uvicorn](https://github.com/ngrok/ngrok-python/tree/main/examples/uvicorn-ngrok.py)\n\n#### Machine Learning\n - Gradio\n - [ngrok-asgi Example](https://github.com/ngrok/ngrok-python/tree/main/examples/gradio/gradio-asgi.py)\n - [gradio CLI Example](https://github.com/ngrok/ngrok-python/tree/main/examples/gradio/gradio-ngrok.py)\n - [OpenPlayground](https://github.com/ngrok/ngrok-python/tree/main/examples/openplayground/run.py)\n - [GPT4ALL](https://github.com/ngrok/ngrok-python/tree/main/examples/gpt4all/run.py)\n - [Stable Diffusion WebUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui/) by AUTOMATIC1111\n - `ngrok-python` is now built-in, see the `--ngrok` and `--ngrok-options` arguments.\n - [Text Generation WebUI](https://github.com/oobabooga/text-generation-webui) by oobabooga\n - `ngrok-python` is now built-in, see the `--extension ngrok` argument.\n\n# Platform Support\n\nPre-built binaries are provided on PyPI for the following platforms:\n\n| OS | i686 | x64 | aarch64 | arm |\n| ---------- | -----|-----|---------|-----|\n| Windows | \u2713 | \u2713 | * | |\n| MacOS | | \u2713 | \u2713 | |\n| Linux | | \u2713 | \u2713 | \u2713 |\n| Linux musl | | \u2713 | \u2713 | |\n| FreeBSD | | * | | |\n\n> **Note**\n> `ngrok-python`, and [ngrok-rust](https://github.com/ngrok/ngrok-rust/) which it depends on, are open source, so it may be possible to build them for other platforms.\n> - Windows-aarch64 will be supported after the next release of [Ring](https://github.com/briansmith/ring/issues/1167).\n> - FreeBSD-x64 is built by the release process, but PyPI won't accept BSD flavors.\n\n# Dependencies\n\n- This project relies on [PyO3](https://pyo3.rs/), an excellent system to ease development and building of Rust plugins for Python.\n- Thank you to [OpenIoTHub](https://github.com/OpenIoTHub/ngrok) for handing over the ngrok name on PyPI.\n\n# Changelog\n\nChanges to `ngrok-python` are tracked under [CHANGELOG.md](https://github.com/ngrok/ngrok-python/blob/main/CHANGELOG.md).\n\n# Join the ngrok Community\n\n- Check out [our official docs](https://docs.ngrok.com)\n- Read about updates on [our blog](https://blog.ngrok.com)\n- Open an [issue](https://github.com/ngrok/ngrok-python/issues) or [pull request](https://github.com/ngrok/ngrok-python/pulls)\n- Join our [Slack community](https://ngrok.com/slack)\n- Follow us on [X / Twitter (@ngrokHQ)](https://twitter.com/ngrokhq)\n- Subscribe to our [Youtube channel (@ngrokHQ)](https://www.youtube.com/@ngrokhq)\n\n# License\n\nThis project is dual-licensed under [Apache, Version 2.0](LICENSE-APACHE) and [MIT](LICENSE-MIT).\nYou can choose between one of them if you use this work.\n\n### Contributions\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in `ngrok-python` by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n\n# Development: Getting Started\n\n**Prerequisites:**\n- a valid Ngrok `authtoken`\n- `make` available in your PATH\n\n1. Update [Cargo.toml](./Cargo.toml) with the _latest supported_ ```ngrok = { version = \"=VERSION_HERE\" }``` from [ngrok-rust](https://github.com/ngrok/ngrok-rust/blob/main/ngrok/Cargo.toml#L3). `ngrok-rust` is used for the bindings in [src/rust_files_here.rs](./src)\n\n2. Run `make build` (builds the `rust` bindings / `python` dependencies)\n\n3. Happy developing!\n\n<br/>\n\n**Example Commands**:\n\n_building the project_\n```shell\nmake develop\n```\n\n_running the entire test suite_\n```shell\n# running the entire test suite\nexport NGROK_AUTHTOKEN=\"YOUR_AUTHTOKEN_HERE\"; make test\n```\n\n_running an individual test_\n```shell\n# running an individual test\nexport NGROK_AUTHTOKEN=\"YOUR_AUTHTOKEN_HERE\"; make test=\"-k TEST_CLASS.NAME_OF_TEST\" test\n```\n\n[See the MakeFile for more examples](./Makefile)\n\n### HTTP2 \n\nThe examples include a minimal `hypercorn` HTTP/2 example if you run `make http2`. You can curl the endpoint logged with `INFO:ngrok.listener:Created` and verify the HTTP/2 response from `hypercorn`.\n\n```bash\ncurl --http2 -v https://<YOUR_LISTENER_URL>\n* Trying <YOUR_IP>:443...\n* Connected to a6278d6c07ce.ngrok.app (<YOUR_IP>) port 443 (#0)\n* ALPN, offering h2\n* ALPN, offering http/1.1\n...\n> GET / HTTP/2\n> Host: a6278d6c07ce.ngrok.app\n> user-agent: curl/7.81.0\n> accept: */*\n>\n...\n< HTTP/2 200\n< content-type: text/plain\n< date: Fri, 01 Mar 2024 18:50:23 GMT\n< ngrok-agent-ips: <YOUR_AGENT_IP>\n< ngrok-trace-id: ed038ace04876818149cf0769bd43e38\n< server: hypercorn-h2\n<\n* TLSv1.2 (IN), TLS header, Supplemental data (23):\n* TLSv1.2 (IN), TLS header, Supplemental data (23):\n* Connection #0 to host <YOUR_LISTENER_URL> left intact\nhello\n```\n\n",
"bugtrack_url": null,
"license": "MIT OR Apache-2.0",
"summary": "The ngrok Agent SDK for Python",
"version": "1.4.0",
"project_urls": {
"changelog": "https://github.com/ngrok/ngrok-python/blob/main/CHANGELOG.md",
"homepage": "https://ngrok.com",
"repository": "https://github.com/ngrok/ngrok-python"
},
"split_keywords": [
"ngrok",
" python",
" pypi",
" pyo3",
" ingress",
" networking"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "31282548a64e673334b804affbf994184896e19c0d0cadb2602c5395d9cb263b",
"md5": "2b2671ec5dd6c05747e18dc2f3f8587f",
"sha256": "05a86cf684120c27d1f10c9a3a5320c7243a89a9f93e58c027dc3916bdeeade9"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl",
"has_sig": false,
"md5_digest": "2b2671ec5dd6c05747e18dc2f3f8587f",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 5278409,
"upload_time": "2024-07-31T22:29:44",
"upload_time_iso_8601": "2024-07-31T22:29:44.857842Z",
"url": "https://files.pythonhosted.org/packages/31/28/2548a64e673334b804affbf994184896e19c0d0cadb2602c5395d9cb263b/ngrok-1.4.0-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "b400dd366c0db00771bf3ff270887f8aa753bd35cc61fc40cbfa4d626d088c07",
"md5": "034bc1ce6a03648e919dcbaf71127855",
"sha256": "166aa4ad1911564e8028436b4c0cc5401f846f79176c97bc84726d417f5483eb"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-macosx_10_12_x86_64.whl",
"has_sig": false,
"md5_digest": "034bc1ce6a03648e919dcbaf71127855",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2731980,
"upload_time": "2024-07-31T22:28:38",
"upload_time_iso_8601": "2024-07-31T22:28:38.317227Z",
"url": "https://files.pythonhosted.org/packages/b4/00/dd366c0db00771bf3ff270887f8aa753bd35cc61fc40cbfa4d626d088c07/ngrok-1.4.0-cp37-abi3-macosx_10_12_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "e337f057c62a81310614381d84ee3cb55badf1f61ba47b35ca15994f1d7e7120",
"md5": "3a597d563f7de2d89aec99599b513395",
"sha256": "2a9bd2fbf3bf2ed8bdc668d20da9f961207ffe8795320598ca2747463c5f980d"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "3a597d563f7de2d89aec99599b513395",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2563059,
"upload_time": "2024-07-31T22:28:56",
"upload_time_iso_8601": "2024-07-31T22:28:56.876433Z",
"url": "https://files.pythonhosted.org/packages/e3/37/f057c62a81310614381d84ee3cb55badf1f61ba47b35ca15994f1d7e7120/ngrok-1.4.0-cp37-abi3-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "104755932abe32af0a3e2ae7a9d4027d76de44095f4f40b9f656495943e4ecb9",
"md5": "f1e8685915880ed9bc3c2a737a683023",
"sha256": "60a6fdaa08c7bcff6b208fb2d1d7d3065ab7bf99a1dfc6e9c4f4535dbbe2e0f6"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
"has_sig": false,
"md5_digest": "f1e8685915880ed9bc3c2a737a683023",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 4587491,
"upload_time": "2024-07-31T22:29:05",
"upload_time_iso_8601": "2024-07-31T22:29:05.664765Z",
"url": "https://files.pythonhosted.org/packages/10/47/55932abe32af0a3e2ae7a9d4027d76de44095f4f40b9f656495943e4ecb9/ngrok-1.4.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "90a14cd711790e4e3cf37150f55c7d05ee0d42f6fe2132c99f48d4b524428517",
"md5": "dd7d1cf7bcf9d0d940984d0fb90e1eee",
"sha256": "381a455b527a4c25e9aa5da231db2f836c243ae46b479f9a4af2b54fadfde906"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
"has_sig": false,
"md5_digest": "dd7d1cf7bcf9d0d940984d0fb90e1eee",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 3002021,
"upload_time": "2024-07-31T22:29:47",
"upload_time_iso_8601": "2024-07-31T22:29:47.321842Z",
"url": "https://files.pythonhosted.org/packages/90/a1/4cd711790e4e3cf37150f55c7d05ee0d42f6fe2132c99f48d4b524428517/ngrok-1.4.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "338905064d76138a58fe1929523035009ca02ae93631c933c660c9bd7fbf18e9",
"md5": "7ba5ab29d961022f784bf2afc52fb2cf",
"sha256": "8660b535a3b1593c80868c80dd2f7b480fcb075ec807ba727868348d037adea3"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "7ba5ab29d961022f784bf2afc52fb2cf",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 3137710,
"upload_time": "2024-07-31T22:29:35",
"upload_time_iso_8601": "2024-07-31T22:29:35.608965Z",
"url": "https://files.pythonhosted.org/packages/33/89/05064d76138a58fe1929523035009ca02ae93631c933c660c9bd7fbf18e9/ngrok-1.4.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "5a99d99ce25e6b9944b4bb9947c3a0cd7097e8ed7c34d4ecf1123d7ae93593a0",
"md5": "a55830978f565f594c256632341cd040",
"sha256": "0f31c5f7a3d93011a08d01ccd38c66b1febec3efe776b301ea677061d56561b1"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-musllinux_1_2_aarch64.whl",
"has_sig": false,
"md5_digest": "a55830978f565f594c256632341cd040",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 3270265,
"upload_time": "2024-07-31T22:28:53",
"upload_time_iso_8601": "2024-07-31T22:28:53.229073Z",
"url": "https://files.pythonhosted.org/packages/5a/99/d99ce25e6b9944b4bb9947c3a0cd7097e8ed7c34d4ecf1123d7ae93593a0/ngrok-1.4.0-cp37-abi3-musllinux_1_2_aarch64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "4ac8d1f85d21156eac54ccb9536d0d9d1032f4d34b28f61db06d8af330768e3a",
"md5": "a16b48f948dab2b79d8dcbe8146fb3f9",
"sha256": "77aeac9d9e1a425c65fad10c7996279ba4099c68af6e18d66d0e9d96f2eef31b"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "a16b48f948dab2b79d8dcbe8146fb3f9",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 3211451,
"upload_time": "2024-07-31T22:31:11",
"upload_time_iso_8601": "2024-07-31T22:31:11.459823Z",
"url": "https://files.pythonhosted.org/packages/4a/c8/d1f85d21156eac54ccb9536d0d9d1032f4d34b28f61db06d8af330768e3a/ngrok-1.4.0-cp37-abi3-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "1bb8eddd57785460d7031792ea64a847ae3cb17ec1602089ae2a945de0ebeefa",
"md5": "6f1e36b20faed403595ac8bfa2848497",
"sha256": "0b2a29f4a98ce62366262fc4906dfb0dfe28a9ec7114dc9e7cbe2d75f923fc00"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-win32.whl",
"has_sig": false,
"md5_digest": "6f1e36b20faed403595ac8bfa2848497",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2473067,
"upload_time": "2024-07-31T22:33:09",
"upload_time_iso_8601": "2024-07-31T22:33:09.854102Z",
"url": "https://files.pythonhosted.org/packages/1b/b8/eddd57785460d7031792ea64a847ae3cb17ec1602089ae2a945de0ebeefa/ngrok-1.4.0-cp37-abi3-win32.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "64fa4dd4b195b7d5702ee2967aa318310f54efa5976cfc9b52cda7ea7bd01270",
"md5": "f3212cc3b89444972fca299d1389bab6",
"sha256": "1ff615ab7709976664730b80e4345d4bf7816b864f990bdf2b6529c7e7f9106d"
},
"downloads": -1,
"filename": "ngrok-1.4.0-cp37-abi3-win_amd64.whl",
"has_sig": false,
"md5_digest": "f3212cc3b89444972fca299d1389bab6",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 3003631,
"upload_time": "2024-07-31T22:31:51",
"upload_time_iso_8601": "2024-07-31T22:31:51.312515Z",
"url": "https://files.pythonhosted.org/packages/64/fa/4dd4b195b7d5702ee2967aa318310f54efa5976cfc9b52cda7ea7bd01270/ngrok-1.4.0-cp37-abi3-win_amd64.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-31 22:29:44",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ngrok",
"github_project": "ngrok-python",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "aiohttp",
"specs": [
[
"==",
"3.9.5"
]
]
},
{
"name": "black",
"specs": [
[
"==",
"23.3.0"
]
]
},
{
"name": "furo",
"specs": [
[
"==",
"2022.12.7"
]
]
},
{
"name": "maturin",
"specs": [
[
"==",
"1.5.1"
]
]
},
{
"name": "mypy",
"specs": [
[
"==",
"1.5.1"
]
]
},
{
"name": "myst_parser",
"specs": [
[
"==",
"1.0.0"
]
]
},
{
"name": "pytest-xdist",
"specs": [
[
"==",
"3.2.0"
]
]
},
{
"name": "pytest-timeout",
"specs": [
[
"==",
"2.1.0"
]
]
},
{
"name": "requests",
"specs": [
[
"==",
"2.28.2"
]
]
},
{
"name": "Sphinx",
"specs": [
[
"==",
"6.1.3"
]
]
}
],
"lcname": "ngrok"
}