markdown-new 0.0.3
Python client library for markdown.new URL-to-Markdown conversion
Requires Python: >=3.9
Keywords: markdown, markdown.new, api, http, python, client

# markdown-new

[![PyPI - Version](https://img.shields.io/pypi/v/markdown-new.svg)](https://pypi.org/project/markdown-new/)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/markdown-new.svg)](https://pypi.org/project/markdown-new/)
[![License](https://img.shields.io/github/license/davelindo/markdown-new-python-client.svg)](LICENSE)

Python client for [`markdown.new`](https://markdown.new/), a Cloudflare-backed service that converts web URLs into Markdown.

## Table of contents

- [What the project does](#what-the-project-does)
- [Why this project is useful](#why-this-project-is-useful)
- [Get started](#get-started)
  - [Installation](#installation)
  - [Quick start (sync)](#quick-start-sync)
  - [Quick start (async)](#quick-start-async)
  - [Batch conversion](#batch-conversion)
- [Configuration and usage patterns](#configuration-and-usage-patterns)
- [Response and errors](#response-and-errors)
- [Testing](#testing)
- [Project help](#project-help)
- [Maintainers and contributing](#maintainers-and-contributing)

## What the project does

`markdown-new` is a lightweight, production-oriented Python client for the public markdown.new conversion endpoint. It handles:

- URL normalization for request-path-based conversions
- Synchronous and asynchronous HTTP client workflows
- Typed request/response handling
- Consistent error mapping for service failures
- Optional authentication header customization
- Lightweight markdown token metadata extraction when present

## Why this project is useful

- **Fast integration**: one method call to convert a URL into Markdown.
- **Reliable transport options**: supports both blocking and `asyncio` usage.
- **Built-in validation**: validates URL inputs (scheme + host) before the network call.
- **Predictable error handling**: clear exception classes for URL, authentication, rate limit, conversion, and transport failures.
- **Type-aware**: `py.typed` marker and explicit response model for IDE-friendly development.
- **Practical ergonomics**: context managers and batch helpers are included for both client types.

## Get started

### Installation

Install from PyPI:

```bash
pip install markdown-new
```

Install with development dependencies:

```bash
pip install -e ".[dev]"
```

### Quick start (sync)

```python
from markdown_new import MarkdownNewClient

with MarkdownNewClient() as client:
    result = client.convert("https://example.com")

print(result.markdown)
print(result.requested_url)
print(result.status_code)
```

### Quick start (async)

```python
import asyncio
from markdown_new import AsyncMarkdownNewClient


async def main() -> None:
    async with AsyncMarkdownNewClient() as client:
        result = await client.convert("https://example.com")
    print(result.markdown)
    print(result.requested_url)


asyncio.run(main())
```

### Batch conversion

```python
from markdown_new import MarkdownNewClient, AsyncMarkdownNewClient

urls = [
    "https://example.com",
    "https://blog.cloudflare.com/markdown-for-agents/",
]

with MarkdownNewClient() as client:
    sync_results = client.convert_many(urls)
    for item in sync_results:
        print(item.requested_url, "->", len(item.markdown), "chars")

async def batch():
    async with AsyncMarkdownNewClient() as client:
        async_results = await client.convert_many(urls, concurrency=5)
    for item in async_results:
        print(item.requested_url, "tokens", item.markdown_tokens)
```

## Configuration and usage patterns

`markdown.new` expects the URL as part of the request path, which means query strings and fragments are encoded by the client automatically.

You can customize request identity and authentication headers with optional client arguments:

```python
from markdown_new import MarkdownNewClient

client = MarkdownNewClient(
    api_key="YOUR_API_KEY",
    api_key_header="Authorization",
    api_key_prefix="Bearer",
    user_agent="my-service/1.0",
    headers={"Accept-Language": "en-US"},
)
```

### HTTP behavior and URL handling

- Supported URL schemes: `http` and `https`
- The client normalizes and URL-encodes target paths for you.
- Timeout is configurable per call or per client instance.
- Batch conversions use the input order.

## Response and errors

Successful calls return `MarkdownResponse`:

- `markdown`: converted Markdown payload
- `requested_url`: original URL passed by the caller
- `normalized_url`: encoded target URL sent to the service
- `status_code`: HTTP status code
- `content_type`: normalized response media type
- `markdown_tokens`: optional token usage metadata from response headers
- `headers`: response headers map

Errors are expressed through:

- `MarkdownNewInvalidURLError` for malformed input
- `MarkdownNewConversionError` for API-level conversion problems
- `MarkdownNewAuthenticationError` for 401/403 responses
- `MarkdownNewRateLimitError` for 429 responses
- `MarkdownNewHTTPError` for other unexpected non-success HTTP errors
- `MarkdownNewRequestError` for transport and unexpected client issues

## Testing

Run unit tests:

```bash
pytest
```

Run live conversion tests against the network endpoint:

```bash
pytest -m integration
```

Recommended local quality gate:

```bash
ruff check .
ruff format .
black --check .
```

If you installed pre-commit, you can run:

```bash
pre-commit install
pre-commit run --all-files
```

## Project help

- Homepage: `markdown.new`
- Issues: https://github.com/davelindo/markdown-new-python-client/issues
- Package metadata: https://github.com/davelindo/markdown-new-python-client
- Package docs: this README and inline docstrings in `markdown_new/`

## Maintainers and contributing

Maintainer:

- Dave Lindon — `dave@knowledge2.ai`

Contributions are welcome:

- Open an issue for bugs, feature requests, or API questions.
- Open a pull request for improvements or fixes.
- See [CONTRIBUTING.md](CONTRIBUTING.md) for full contribution guidelines.
- Prefer `MarkdownNewClient` and `AsyncMarkdownNewClient` changes to include tests in `tests/`.