LLM with no restrictions: integrate it with the OpenAI SDK
Integrating an LLM with no restrictions takes three changes to a standard OpenAI client: the base URL, the key and the model name. The rest of this walkthrough covers system prompts, streaming, tools and the error handling a production app needs.
Last updated

The three changes
If your code already talks to an OpenAI-style API, you are almost done. Swap these three values:
- Base URL:
https://api.llmwithoutrestrictions.com/v1 - Key: sent as
Authorization: Bearer <key>. The SDK does this for you. Get a key on the API key page. - Model:
uncensored
Python:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.llmwithoutrestrictions.com/v1",
api_key=os.environ["API_KEY"],
)
r = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You are a concise assistant."},
{"role": "user", "content": "List three uses for a tide table."},
],
)
print(r.choices[0].message.content)
print(r.usage)
Node:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.llmwithoutrestrictions.com/v1",
apiKey: process.env.API_KEY,
});
const r = await client.chat.completions.create({
model: "uncensored",
messages: [{ role: "user", content: "List three uses for a tide table." }],
});
console.log(r.choices[0].message.content);
The API also accepts POST /v1/responses and lists the model on GET /v1/models, in case your framework calls either.
Writing the system prompt
With a model tuned not to refuse lawful requests, the system prompt does a different job than it does on a filtered API. You are no longer spending words talking the model into helping. You use them to define the product. Good system prompts for this kind of model share a few habits:
- State the role and setting plainly. "You are the narrator of a dark fantasy text adventure for adult players" is better than a long list of permissions.
- Fix the output format. Say how long replies should be, whether to use markdown, and when to ask a question instead of answering.
- Put hard rules in one short list. The model follows five clear rules better than twenty overlapping ones.
- Keep persona facts stable. Names, tone and backstory belong in the system message so they survive a long chat. Remember that the context window is 100,000 tokens for prompt plus reply, so there is room.
- Lower the temperature for structure, raise it for prose. Around 0.2 for extraction, 0.8 to 1.0 for creative writing.
A model without refusals does not remove your responsibility for the application. You still decide who can use it, what your own terms are, and what your app should not do. The one limit the service itself enforces is no sexual content involving minors, so build any age gating and moderation your product needs on your side.
Streaming
Set stream: true to receive tokens over server-sent events, with usage reported at the end. In Python:
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.llmwithoutrestrictions.com/v1", api_key=os.environ["API_KEY"])
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Describe a lighthouse at dusk."}],
stream=True,
stream_options={"include_usage": True},
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.usage:
print("\n", chunk.usage)
One detail matters for reliability: a streamed request occupies its concurrency slot until the stream ends. If a user closes the tab and your server keeps the connection open, that slot stays taken. Close the stream when the client disconnects.
Sampling settings worth knowing
These parameters are passed through to the model: temperature, top_p, stop, seed and the frequency and presence penalties. Three habits pay off. Change one setting at a time, so you know what caused a difference. Use seed with a fixed prompt when you compare prompt versions, so a change in wording is not hidden by random variation. And add a presence or frequency penalty when long creative replies start repeating phrases. Leave max_tokens out when you want the model to finish naturally; the completion may use whatever remains of the 100,000-token window.
Tools and JSON mode
Tool calling follows the OpenAI format: pass tools and tool_choice, read tool_calls from the reply, run the function yourself and send the result back as a message with role: "tool". For structured output, add response_format={"type": "json_object"} and say in the prompt that the answer must be JSON.
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api.llmwithoutrestrictions.com/v1", api_key=os.environ["API_KEY"])
r = client.chat.completions.create(
model="uncensored",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Reply with a JSON object only."},
{"role": "user", "content": "Give name, mood and tagline for a fictional tavern."},
],
)
data = json.loads(r.choices[0].message.content)
print(data)
Always wrap json.loads in a try block. JSON mode makes valid JSON likely, and your code should still survive the rare reply that is cut off or malformed.
Error handling that holds up
The error you will meet in practice is HTTP 429, and it has three causes you can tell apart:
- Error code
rate_limited: too many requests per minute (300 on a full key, 60 on a trial key). - Error code
concurrency: too many requests at once (8 on a full key, 2 on a trial key). - A 429 with a
Retry-After: 5header: temporary overload. Wait that long and try again.
A wrapper that honours Retry-After and falls back to exponential backoff, plus a semaphore that keeps you under the concurrency limit:
import os, time, threading
from openai import OpenAI, RateLimitError
client = OpenAI(
base_url="https://api.llmwithoutrestrictions.com/v1",
api_key=os.environ["API_KEY"],
max_retries=0,
)
slots = threading.Semaphore(8) # use 2 on a trial key
def ask(messages, tries=5):
for attempt in range(tries):
with slots:
try:
r = client.chat.completions.create(model="uncensored", messages=messages)
return r.choices[0].message.content
except RateLimitError as e:
wait = float(e.response.headers.get("Retry-After", 2 ** attempt))
time.sleep(wait)
raise RuntimeError("still rate limited after retries")
Notice that the sleep happens outside the semaphore, so a waiting thread does not block a slot. Failed or refused requests are not charged, so retrying costs nothing extra. The response headers X-RateLimit-Limit-Requests and X-RateLimit-Limit-Concurrency tell you the limits that apply to your key, and X-Request-Id is worth logging for any report to support.
Testing the integration before launch
Most integration bugs show up under a few simple tests. Run them with a trial key, whose limit of 2 concurrent requests exposes problems early:
- Fire three requests at once and confirm the third returns a 429 with code
concurrency, and that your wrapper waits and retries instead of crashing. - Start a stream, then close the client halfway. Check that your server closes the upstream stream too, so the slot is freed.
- Feed a long conversation history and confirm your app trims or summarizes it long before it nears the 100,000-token window.
- Return a deliberately broken JSON string from a stub and make sure your parsing code handles it.
- Log
X-Request-Idfor every call, so a single bad reply can be traced later.
Ten minutes on this list catches the failures that otherwise appear on launch day, when several users send messages at the same moment.
Before you ship
Check the body size (8 MB maximum), set a sensible max_tokens if you want to cap cost, and watch X-Balance-USD so a low balance triggers an alert rather than an outage. You can also poll GET /v1/balance. Cost is easy to estimate: at $0.15 per 1M input and $0.50 per 1M output tokens, a request with 3,000 input and 600 output tokens costs $0.00045 plus $0.0003, so $0.00075. The documentation has the full parameter list, and our piece on what developers need to know covers the policy questions around unfiltered models.
More guides
Common questions
Do I need a special SDK?
No. Any OpenAI SDK or client works. Change the base URL, the key and the model name to uncensored.
Why do I get a 429 when I send only a few requests?
Check the error code. concurrency means too many requests at once, often open streams. rate_limited means too many per minute. A Retry-After: 5 header means a brief overload.
Are failed requests billed?
No. Failed or refused requests are not charged.
Does the system prompt still matter?
Yes. It sets role, format and persona. It no longer has to coax the model into answering lawful requests.
Get your API key
Sign up, copy the key, update the base URL. That is all.