{
  "openapi": "3.1.0",
  "info": {
    "title": "NoJunk Web Read",
    "version": "1.0.0",
    "description": "Read any public web page as clean JSON: title, description, site name, publish date, language, readable text (boilerplate removed), Markdown and the page's links. Give it a URL, get the content back in one call. HTML, plain text, JSON and XML pages supported.",
    "x-guidance": "Use this to read the content of a web page cheaply instead of scraping it yourself: GET /read?url=https://example.com/article (or POST /read with JSON body {\"url\": \"...\"}) returns the page's title, description, site name, publish date, language, clean readable text with navigation/ads/scripts stripped, a Markdown rendering, and up to 50 links, all as JSON. Costs $0.002 USDC on Base per request via x402; you are only charged for a successful read (2xx upstream, readable content type). It fetches live, server-rendered HTML; pages that render only with JavaScript may return little text. Only public http(s) URLs are accepted (no localhost, private networks or internal hostnames). Text and markdown are capped at 60,000 characters (truncated=true when cut) and bodies at 3 MB. Follows up to 5 redirects, 8 second timeout. Best for: reading articles, docs, blog posts, product pages, JSON APIs and feeds for summarizing, answering questions or extracting facts."
  },
  "servers": [
    {
      "url": "https://nojunk-web-read.mick8511.workers.dev"
    }
  ],
  "paths": {
    "/read": {
      "get": {
        "operationId": "readPage",
        "summary": "Read a public web page: title, metadata, clean text, Markdown and links as JSON",
        "tags": [
          "Web",
          "Scraping",
          "Reader",
          "Content"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Absolute http(s) URL of the public web page to read, e.g. 'https://example.com/article'. Localhost, private-network and internal hostnames are rejected."
          }
        ],
        "responses": {
          "200": {
            "description": "Page content",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "description": "The URL that was requested (normalized)"
                    },
                    "final_url": {
                      "type": "string",
                      "description": "The URL that actually served the page, after up to 5 redirects"
                    },
                    "status": {
                      "type": "integer",
                      "description": "Upstream HTTP status (always 2xx on success)"
                    },
                    "content_type": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Upstream media type, e.g. text/html"
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Page title (og:title, <title> or first <h1>)"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Meta description / og:description"
                    },
                    "site_name": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "og:site_name if present"
                    },
                    "published": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Publish date from page metadata if present (article:published_time, meta date, <time datetime>)"
                    },
                    "lang": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Page language (<html lang> or content-language)"
                    },
                    "text": {
                      "type": "string",
                      "description": "Clean readable text of the main content: navigation, headers, footers, sidebars, scripts and styles removed; entities decoded; whitespace collapsed; paragraph breaks kept. For JSON pages: pretty-printed JSON. Capped at 60,000 characters."
                    },
                    "markdown": {
                      "type": "string",
                      "description": "Same content as Markdown: headings as #, links as [text](href), lists as -, code blocks fenced, tables as rows. Capped at 60,000 characters."
                    },
                    "links": {
                      "type": "array",
                      "maxItems": 50,
                      "items": {
                        "type": "object",
                        "properties": {
                          "text": {
                            "type": "string"
                          },
                          "href": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "text",
                          "href"
                        ]
                      },
                      "description": "Up to 50 absolute http(s) links, main content first, duplicates removed"
                    },
                    "word_count": {
                      "type": "integer",
                      "description": "Words in the full (uncapped) text"
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "true if the body exceeded 3 MB or text/markdown were cut at 60,000 characters"
                    },
                    "fetched_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "url",
                    "final_url",
                    "status",
                    "title",
                    "text",
                    "markdown",
                    "links",
                    "word_count",
                    "truncated",
                    "fetched_at"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Missing, malformed, non-http(s) or private/internal URL (no charge)"
          },
          "402": {
            "description": "Payment Required"
          },
          "404": {
            "description": "The page was not found upstream (HTTP 404/410) (no charge)"
          },
          "413": {
            "description": "Request body too large (no charge)"
          },
          "415": {
            "description": "The URL is not an HTML, text, JSON or XML document, e.g. a PDF, image or binary file (no charge)"
          },
          "502": {
            "description": "The page could not be fetched: upstream error status, timeout (8 s), too many redirects, or a redirect to a blocked address (no charge)"
          }
        }
      },
      "post": {
        "operationId": "readPagePost",
        "summary": "Read a public web page: title, metadata, clean text, Markdown and links as JSON",
        "tags": [
          "Web",
          "Scraping",
          "Reader",
          "Content"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048,
                    "description": "Absolute http(s) URL of the public web page to read, e.g. 'https://example.com/article'. Localhost, private-network and internal hostnames are rejected."
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Page content",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "description": "The URL that was requested (normalized)"
                    },
                    "final_url": {
                      "type": "string",
                      "description": "The URL that actually served the page, after up to 5 redirects"
                    },
                    "status": {
                      "type": "integer",
                      "description": "Upstream HTTP status (always 2xx on success)"
                    },
                    "content_type": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Upstream media type, e.g. text/html"
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Page title (og:title, <title> or first <h1>)"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Meta description / og:description"
                    },
                    "site_name": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "og:site_name if present"
                    },
                    "published": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Publish date from page metadata if present (article:published_time, meta date, <time datetime>)"
                    },
                    "lang": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Page language (<html lang> or content-language)"
                    },
                    "text": {
                      "type": "string",
                      "description": "Clean readable text of the main content: navigation, headers, footers, sidebars, scripts and styles removed; entities decoded; whitespace collapsed; paragraph breaks kept. For JSON pages: pretty-printed JSON. Capped at 60,000 characters."
                    },
                    "markdown": {
                      "type": "string",
                      "description": "Same content as Markdown: headings as #, links as [text](href), lists as -, code blocks fenced, tables as rows. Capped at 60,000 characters."
                    },
                    "links": {
                      "type": "array",
                      "maxItems": 50,
                      "items": {
                        "type": "object",
                        "properties": {
                          "text": {
                            "type": "string"
                          },
                          "href": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "text",
                          "href"
                        ]
                      },
                      "description": "Up to 50 absolute http(s) links, main content first, duplicates removed"
                    },
                    "word_count": {
                      "type": "integer",
                      "description": "Words in the full (uncapped) text"
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "true if the body exceeded 3 MB or text/markdown were cut at 60,000 characters"
                    },
                    "fetched_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "url",
                    "final_url",
                    "status",
                    "title",
                    "text",
                    "markdown",
                    "links",
                    "word_count",
                    "truncated",
                    "fetched_at"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Missing, malformed, non-http(s) or private/internal URL (no charge)"
          },
          "402": {
            "description": "Payment Required"
          },
          "404": {
            "description": "The page was not found upstream (HTTP 404/410) (no charge)"
          },
          "413": {
            "description": "Request body too large (no charge)"
          },
          "415": {
            "description": "The URL is not an HTML, text, JSON or XML document, e.g. a PDF, image or binary file (no charge)"
          },
          "502": {
            "description": "The page could not be fetched: upstream error status, timeout (8 s), too many redirects, or a redirect to a blocked address (no charge)"
          }
        }
      }
    }
  }
}