Domains¶
This page covers domain management operations: listing domains, nameservers, URL forwarding, glue records, and availability checks.
Quick Start¶
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
# List all domains
domains = await piglet.domains.list()
for domain in domains:
print(f"{domain.domain} - expires {domain.expire_date}")
# Check domain availability
availability = await piglet.domains.check("coolname.com")
if availability.available:
print(f"Available for ${availability.pricing.registration}!")
from oinker import Piglet
with Piglet() as piglet:
# List all domains
domains = piglet.domains.list()
for domain in domains:
print(f"{domain.domain} - expires {domain.expire_date}")
# Check domain availability
availability = piglet.domains.check("coolname.com")
if availability.available:
print(f"Available for ${availability.pricing.registration}!")
List Domains¶
List all domains in your Porkbun account.
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
# Basic listing
domains = await piglet.domains.list()
for domain in domains:
print(f"Domain: {domain.domain}")
print(f" Status: {domain.status}")
print(f" Created: {domain.create_date}")
print(f" Expires: {domain.expire_date}")
print(f" Auto-renew: {domain.auto_renew}")
print(f" WHOIS Privacy: {domain.whois_privacy}")
print(f" Security Lock: {domain.security_lock}")
print("---")
from oinker import Piglet
with Piglet() as piglet:
# Basic listing
domains = piglet.domains.list()
for domain in domains:
print(f"Domain: {domain.domain}")
print(f" Status: {domain.status}")
print(f" Created: {domain.create_date}")
print(f" Expires: {domain.expire_date}")
print(f" Auto-renew: {domain.auto_renew}")
print(f" WHOIS Privacy: {domain.whois_privacy}")
print(f" Security Lock: {domain.security_lock}")
print("---")
With Labels¶
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
# Include label information
domains = await piglet.domains.list(include_labels=True)
for domain in domains:
if domain.labels:
labels = ", ".join(label.title for label in domain.labels)
print(f"{domain.domain} [{labels}]")
else:
print(f"{domain.domain} [no labels]")
from oinker import Piglet
with Piglet() as piglet:
# Include label information
domains = piglet.domains.list(include_labels=True)
for domain in domains:
if domain.labels:
labels = ", ".join(label.title for label in domain.labels)
print(f"{domain.domain} [{labels}]")
else:
print(f"{domain.domain} [no labels]")
Pagination (1000+ Domains)¶
Domains are returned in chunks of 1000. Use pagination for large accounts:
Nameservers¶
Get Nameservers¶
Update Nameservers¶
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
# Use custom nameservers
await piglet.domains.update_nameservers(
"example.com",
[
"ns1.example.com",
"ns2.example.com",
]
)
print("Nameservers updated!")
# Switch to Cloudflare
await piglet.domains.update_nameservers(
"example.com",
[
"nova.ns.cloudflare.com",
"zara.ns.cloudflare.com",
]
)
# Switch back to Porkbun
await piglet.domains.update_nameservers(
"example.com",
[
"curitiba.ns.porkbun.com",
"fortaleza.ns.porkbun.com",
"maceio.ns.porkbun.com",
"salvador.ns.porkbun.com",
]
)
from oinker import Piglet
with Piglet() as piglet:
# Use custom nameservers
piglet.domains.update_nameservers(
"example.com",
[
"ns1.example.com",
"ns2.example.com",
]
)
print("Nameservers updated!")
# Switch to Cloudflare
piglet.domains.update_nameservers(
"example.com",
[
"nova.ns.cloudflare.com",
"zara.ns.cloudflare.com",
]
)
# Switch back to Porkbun
piglet.domains.update_nameservers(
"example.com",
[
"curitiba.ns.porkbun.com",
"fortaleza.ns.porkbun.com",
"maceio.ns.porkbun.com",
"salvador.ns.porkbun.com",
]
)
URL Forwarding¶
List URL Forwards¶
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
forwards = await piglet.domains.get_url_forwards("example.com")
for forward in forwards:
subdomain = forward.subdomain or "@"
print(f"ID: {forward.id}")
print(f" {subdomain}.example.com -> {forward.location}")
print(f" Type: {forward.type}")
print(f" Include path: {forward.include_path}")
print(f" Wildcard: {forward.wildcard}")
print("---")
from oinker import Piglet
with Piglet() as piglet:
forwards = piglet.domains.get_url_forwards("example.com")
for forward in forwards:
subdomain = forward.subdomain or "@"
print(f"ID: {forward.id}")
print(f" {subdomain}.example.com -> {forward.location}")
print(f" Type: {forward.type}")
print(f" Include path: {forward.include_path}")
print(f" Wildcard: {forward.wildcard}")
print("---")
Add URL Forward¶
from oinker import AsyncPiglet, URLForwardCreate
async with AsyncPiglet() as piglet:
# Simple redirect (root domain)
await piglet.domains.add_url_forward(
"example.com",
URLForwardCreate(
location="https://www.example.com",
type="permanent",
)
)
# Subdomain redirect
await piglet.domains.add_url_forward(
"example.com",
URLForwardCreate(
subdomain="blog",
location="https://blog.example.com",
type="permanent",
)
)
# Temporary redirect with path preservation
await piglet.domains.add_url_forward(
"example.com",
URLForwardCreate(
subdomain="old",
location="https://new.example.com",
type="temporary",
include_path=True,
)
)
# Wildcard redirect (all subdomains)
await piglet.domains.add_url_forward(
"example.com",
URLForwardCreate(
location="https://main.example.com",
type="permanent",
wildcard=True,
)
)
from oinker import Piglet, URLForwardCreate
with Piglet() as piglet:
# Simple redirect (root domain)
piglet.domains.add_url_forward(
"example.com",
URLForwardCreate(
location="https://www.example.com",
type="permanent",
)
)
# Subdomain redirect
piglet.domains.add_url_forward(
"example.com",
URLForwardCreate(
subdomain="blog",
location="https://blog.example.com",
type="permanent",
)
)
# Temporary redirect with path preservation
piglet.domains.add_url_forward(
"example.com",
URLForwardCreate(
subdomain="old",
location="https://new.example.com",
type="temporary",
include_path=True,
)
)
# Wildcard redirect (all subdomains)
piglet.domains.add_url_forward(
"example.com",
URLForwardCreate(
location="https://main.example.com",
type="permanent",
wildcard=True,
)
)
Delete URL Forward¶
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
# First, get the forward ID
forwards = await piglet.domains.get_url_forwards("example.com")
for forward in forwards:
if forward.subdomain == "old":
await piglet.domains.delete_url_forward(
"example.com",
forward_id=forward.id
)
print(f"Deleted forward: {forward.id}")
from oinker import Piglet
with Piglet() as piglet:
# First, get the forward ID
forwards = piglet.domains.get_url_forwards("example.com")
for forward in forwards:
if forward.subdomain == "old":
piglet.domains.delete_url_forward(
"example.com",
forward_id=forward.id
)
print(f"Deleted forward: {forward.id}")
Domain Availability¶
Check if a domain is available for registration.
Rate Limited
Domain checks are rate limited by Porkbun. The response includes rate limit information.
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
availability = await piglet.domains.check("coolname.com")
if availability.available:
print(f"✅ coolname.com is available!")
print(f" Registration: ${availability.pricing.registration}")
print(f" Renewal: ${availability.pricing.renewal}")
print(f" Transfer: ${availability.pricing.transfer}")
if availability.first_year_promo:
print(f" 🎉 First year promo! Regular: ${availability.regular_price}")
else:
print("❌ coolname.com is taken")
if availability.premium:
print(" ⭐ This is a premium domain")
from oinker import Piglet
with Piglet() as piglet:
availability = piglet.domains.check("coolname.com")
if availability.available:
print(f"✅ coolname.com is available!")
print(f" Registration: ${availability.pricing.registration}")
print(f" Renewal: ${availability.pricing.renewal}")
print(f" Transfer: ${availability.pricing.transfer}")
if availability.first_year_promo:
print(f" 🎉 First year promo! Regular: ${availability.regular_price}")
else:
print("❌ coolname.com is taken")
if availability.premium:
print(" ⭐ This is a premium domain")
Check Multiple TLDs¶
import asyncio
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
base_name = "myawesomebrand"
tlds = ["com", "net", "org", "io", "dev", "app"]
for tld in tlds:
domain = f"{base_name}.{tld}"
try:
availability = await piglet.domains.check(domain)
status = "✅" if availability.available else "❌"
price = f"${availability.pricing.registration}" if availability.available else "taken"
print(f"{status} {domain}: {price}")
except Exception as e:
print(f"⚠️ {domain}: {e}")
# Small delay to respect rate limits
await asyncio.sleep(0.5)
import time
from oinker import Piglet
with Piglet() as piglet:
base_name = "myawesomebrand"
tlds = ["com", "net", "org", "io", "dev", "app"]
for tld in tlds:
domain = f"{base_name}.{tld}"
try:
availability = piglet.domains.check(domain)
status = "✅" if availability.available else "❌"
price = f"${availability.pricing.registration}" if availability.available else "taken"
print(f"{status} {domain}: {price}")
except Exception as e:
print(f"⚠️ {domain}: {e}")
# Small delay to respect rate limits
time.sleep(0.5)
Glue Records¶
Glue records are used when you run your own nameservers on subdomains of your domain.
List Glue Records¶
Create Glue Record¶
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
# IPv4 only
await piglet.domains.create_glue_record(
"example.com",
subdomain="ns1",
ips=["192.168.1.1"]
)
# IPv4 and IPv6
await piglet.domains.create_glue_record(
"example.com",
subdomain="ns2",
ips=["192.168.1.2", "2001:db8::1"]
)
print("Glue records created!")
from oinker import Piglet
with Piglet() as piglet:
# IPv4 only
piglet.domains.create_glue_record(
"example.com",
subdomain="ns1",
ips=["192.168.1.1"]
)
# IPv4 and IPv6
piglet.domains.create_glue_record(
"example.com",
subdomain="ns2",
ips=["192.168.1.2", "2001:db8::1"]
)
print("Glue records created!")
Update Glue Record¶
Updates replace all existing IPs with the new list.
Delete Glue Record¶
Real-World Patterns¶
Find Expiring Domains¶
from datetime import datetime, timedelta
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
domains = await piglet.domains.list()
# Find domains expiring in the next 30 days
threshold = datetime.now() + timedelta(days=30)
expiring = [
d for d in domains
if d.expire_date and d.expire_date < threshold
]
if expiring:
print("⚠️ Domains expiring soon:")
for domain in sorted(expiring, key=lambda d: d.expire_date):
days_left = (domain.expire_date - datetime.now()).days
print(f" {domain.domain}: {days_left} days left")
else:
print("✅ No domains expiring in the next 30 days")
from datetime import datetime, timedelta
from oinker import Piglet
with Piglet() as piglet:
domains = piglet.domains.list()
# Find domains expiring in the next 30 days
threshold = datetime.now() + timedelta(days=30)
expiring = [
d for d in domains
if d.expire_date and d.expire_date < threshold
]
if expiring:
print("⚠️ Domains expiring soon:")
for domain in sorted(expiring, key=lambda d: d.expire_date):
days_left = (domain.expire_date - datetime.now()).days
print(f" {domain.domain}: {days_left} days left")
else:
print("✅ No domains expiring in the next 30 days")
Audit Domain Security Settings¶
from oinker import AsyncPiglet
async with AsyncPiglet() as piglet:
domains = await piglet.domains.list()
print("Security Audit:")
print("-" * 60)
for domain in domains:
issues = []
if not domain.security_lock:
issues.append("🔓 Security lock disabled")
if not domain.whois_privacy:
issues.append("👁️ WHOIS privacy disabled")
if not domain.auto_renew:
issues.append("⏰ Auto-renew disabled")
if issues:
print(f"\n{domain.domain}:")
for issue in issues:
print(f" {issue}")
else:
print(f"\n{domain.domain}: ✅ All good!")
from oinker import Piglet
with Piglet() as piglet:
domains = piglet.domains.list()
print("Security Audit:")
print("-" * 60)
for domain in domains:
issues = []
if not domain.security_lock:
issues.append("🔓 Security lock disabled")
if not domain.whois_privacy:
issues.append("👁️ WHOIS privacy disabled")
if not domain.auto_renew:
issues.append("⏰ Auto-renew disabled")
if issues:
print(f"\n{domain.domain}:")
for issue in issues:
print(f" {issue}")
else:
print(f"\n{domain.domain}: ✅ All good!")